Ich arbeitete mit einer Abfrage, die ich heute schrieb, musste den Code aus der WHERE
Klausel ändern , um einen IN-Filter (List of Stuff) zu verwenden, anstatt so etwas zu verwenden
item_desc = 'item 1'
OR item_desc = 'item 2'
OR item_desc = 'item 3'
OR item_desc = 'item 4'
Das obige lief 15 Minuten lang und gab nichts zurück, aber das Folgende gab mir meine Ergebnismenge in 1,5 Minuten
item_desc IN (
'item 1'
,'item 2'
,'item 3'
,'item 4'
)
Ich habe dies in SQL getan und frage mich, warum die IN-Anweisung (Liste der Elemente) so viel schneller ausgeführt wurde als die OR-Anweisung.
- BEARBEITEN - SQL Server 2008, ich entschuldige mich dafür, dass ich diese Informationen nicht in erster Linie eingegeben habe.
Hier ist die Abfrage in ihrer Gesamtheit mit den OR
Anweisungen:
DECLARE @SD DATETIME
DECLARE @ED DATETIME
SET @SD = '2013-06-01';
SET @ED = '2013-06-15';
-- COLUMN SELECTION
SELECT PV.PtNo_Num AS 'VISIT ID'
, PV.Med_Rec_No AS 'MRN'
, PV.vst_start_dtime AS 'ADMIT'
, PV.vst_end_dtime AS 'DISC'
, PV.Days_Stay AS 'LOS'
, PV.pt_type AS 'PT TYPE'
, PV.hosp_svc AS 'HOSP SVC'
, SO.ord_no AS 'ORDER NUMBER'
--, SO.ent_dtime AS 'ORDER ENTRY TIME'
--, DATEDIFF(HOUR,PV.vst_start_dtime,SO.ent_dtime) AS 'ADM TO ENTRY HOURS'
, SO.svc_desc AS 'ORDER DESCRIPTION'
, OSM.ord_sts AS 'ORDER STATUS'
, SOS.prcs_dtime AS 'ORDER STATUS TIME'
, DATEDIFF(DAY,PV.vst_start_dtime,SOS.prcs_dtime) AS 'ADM TO ORD STS IN DAYS'
-- DB(S) USED
FROM smsdss.BMH_PLM_PtAcct_V PV
JOIN smsmir.sr_ord SO
ON PV.PtNo_Num = SO.episode_no
JOIN smsmir.sr_ord_sts_hist SOS
ON SO.ord_no = SOS.ord_no
JOIN smsmir.ord_sts_modf_mstr OSM
ON SOS.hist_sts = OSM.ord_sts_modf_cd
-- FILTER(S)
WHERE PV.Adm_Date BETWEEN @SD AND @ED
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
AND SO.ord_no NOT IN (
SELECT SO.ord_no
FRROM smsdss.BMH_PLM_PtAcct_V PV
JOIN smsmir.sr_ord SO
ON PV.PtNo_Num = SO.episode_no
JOIN smsmir.sr_ord_sts_hist SOS
ON SO.ord_no = SOS.ord_no
JOIN smsmir.ord_sts_modf_mstr OSM
ON SOS.hist_sts = OSM.ord_sts_modf_cd
WHERE OSM.ord_sts = 'DISCONTINUE'
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
)
ORDER BY PV.PtNo_Num, SO.ord_no, SOS.prcs_dtime
Vielen Dank,
OR
Sie wie in der obigen Abfrage verwenden, können Sie den Motor kurzschließen.WHERE A AND B OR C
wird als wahr ausgewertet, auch wenn A UND B falsch sind, wenn C wahr ist. Wenn Sie sagen,WHERE A and B OR C OR D OR E OR F
wie Sie es oben tun,AND
können Sie das ausklammern. Die tatsächliche äquivalente Logik würde die einzukapselnOR
Serie oben in Klammern , so dass sie als ein Satz behandelt werden:WHERE A AND (B OR C OR D OR E)
. SoIN
wird behandelt.AND
zuvor behandeltOR
wurde. Ihre obige Abfrage entspricht also,WHERE (OSM.ord_sts = 'DISCONTINUE' AND SO.svc_cd = 'PCO_REMFOLEY') OR SO.svc_cd = 'PCO_INSRTFOLEY' OR SO.svc_cd = 'PCO_INSTFOLEY' OR SO.svc_cd = 'PCO_URIMETER'
dass der Rest der Auswertung kurzgeschlossen werden kann, wenn eine der letzten drei Bedingungen zutrifft.Antworten:
Oleskis Antwort ist falsch. Für SQL Server 2008 wird eine
IN
Liste in eine Reihe vonOR
Anweisungen umgestaltet . Dies kann beispielsweise in MySQL anders sein.Ich bin mir ziemlich sicher, dass die tatsächlichen Ausführungspläne für beide Abfragen identisch sind.
Höchstwahrscheinlich lief die zweite Abfrage schneller, weil Sie sie als zweite ausgeführt haben , und die erste Abfrage hat bereits alle Datenseiten aus der Datenbank abgerufen und die E / A-Kosten bezahlt. Die zweite Abfrage war in der Lage, alle Daten aus dem Speicher zu lesen und viel schneller auszuführen.
Aktualisieren
Die tatsächliche Quelle der Varianz ist wahrscheinlich, dass die Abfragen nicht gleichwertig sind . Sie haben zwei verschiedene
OR
Listen:und später
In diesen beiden
WHERE
Abschnitten bedeutet die Operatorpräzision (wobei AND vor OR behandelt wird), dass die tatsächliche Logik, die von der Engine ausgeführt wird, Folgendes ist:Wenn Sie die
OR
Listen durch einenIN
Ausdruck ersetzen, lautet die Logik:Welches ist radikal anders.
quelle
IN
istOR
aufgrund der anderen Bedingungen in IhrerWHERE
Klausel in der eigentlichen Abfrage nicht gleichbedeutend mit den oben genannten . Grundsätzlich werden die Abfragen unterschiedliche Ergebnisse zurückgeben.Der beste Weg, dies zu erkennen, besteht darin, sich den tatsächlichen Abfrageplan mit etwas Ähnlichem anzusehen
EXPLAIN
. Dies sollte Ihnen genau sagen, was das DBMS tut, und dann können Sie eine viel bessere Vorstellung davon bekommen, warum es effizienter ist.Trotzdem können DBMS-Systeme wirklich gut Operationen zwischen zwei Tabellen ausführen (wie Joins). Ein großer Teil der Zeit des Optimierers wird für diese Teile der Abfragen aufgewendet, da sie im Allgemeinen teurer sind.
Beispielsweise könnte das DBMS diese
IN
Liste sortieren und mithilfe eines Indexesitem_desc
die Ergebnisse sehr schnell filtern. Sie können diese Optimierung nicht durchführen, wenn Sie eine Reihe von Auswahlen wie im ersten Beispiel auflisten.Wenn Sie verwenden
IN
, erstellen Sie eine spontane Tabelle und filtern mithilfe dieser effizienteren Tabellenkombinationstechniken.EDIT : Ich habe diese Antwort gepostet, bevor OP das spezifische DBMS erwähnte. Es stellt sich heraus, dass SQL Server diese Abfrage NICHT behandelt, sondern möglicherweise für andere DBMS-Systeme gültig ist. Siehe JNK Antwort für eine bestimmte, genaue Antwort.
quelle
IN
wäre nicht so schnell, wenn es sich um eine Unterauswahl mit 100 Datensätzen oder tausend Datensätzen handeln würde.IN
Anweisung nicht in eine Tabelle konvertiert, sondern wie eine Reihe vonOR
s behandelt.