Frage

Ich habe mit einer Abfrage gearbeitet, die ich heute geschrieben habe, um den Code von der zu ändern WHERE klausel, 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 mein Ergebnis in 1,5 Minuten

item_desc IN (
'item 1'
,'item 2'
,'item 3'
,'item 4'
)

Ich habe das in SQL gemacht und frage mich, warum die IN (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 an erster Stelle eingefügt habe.

Hier ist die Abfrage in ihrer Gesamtheit mit dem OR Erklärungen:

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

Danke,

War es hilfreich?

Lösung

Oleskis Antwort ist falsch.Für SQL Server 2008, ein IN liste wird in eine Reihe von umgestaltet OR Erklärungen.Es kann anders sein, sagen wir MySQL.

Ich bin mir ziemlich sicher, dass wenn Sie tatsächliche Ausführungspläne für Ihre beiden Abfragen generieren würden, diese identisch wären.

Aller Wahrscheinlichkeit nach lief die zweite Abfrage schneller weil du es als zweiter gelaufen bist, und die erste Abfrage hatte bereits alle Datenseiten aus der Datenbank gezogen und die E / A-Kosten bezahlt.Die zweite Abfrage konnte alle Daten aus dem Speicher lesen und viel schneller ausführen.

Update

Die tatsächliche Quelle der Varianz ist wahrscheinlich, dass die Abfragen sind nicht gleichwertig.Sie haben zwei verschiedene OR listen unten:

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'

und später

 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'

In diesen beiden WHERE klauseln, Operatorpräzendenz (where UND wird vor OR behandelt) bedeutet, dass die eigentliche Logik, die von der Engine ausgeführt wird, ist:

WHERE (ConditionA AND ConditionB)
OR ConditionC
OR ConditionD
OR ConditionE

Wenn Sie die ersetzen OR listen mit einem IN ausdruck, die Logik wird sein:

WHERE ConditionA
AND (ConditionB OR ConditionC OR ConditionD OR ConditionE)

Was radikal anders ist.

Andere Tipps

Der beste Weg, dies zu erkennen, besteht darin, den tatsächlichen Abfrageplan mit etwas wie zu betrachten 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.

Vor diesem Hintergrund sind DBMS-Systeme wirklich gut darin, Operationen zwischen zwei Tabellen (wie Joins) auszuführen.Ein Großteil der Zeit des Optimierers wird für diese Teile der Abfragen aufgewendet, da sie im Allgemeinen teurer sind.

Zum Beispiel könnte das DBMS das sortieren IN liste und unter Verwendung eines Indexes auf item_desc, filtern Sie die Ergebnisse sehr schnell.Sie können diese Optimierung nicht durchführen, wenn Sie wie im ersten Beispiel eine Reihe von Auswahlen auflisten.

Wenn Sie verwenden IN, Sie erstellen eine spontane Tabelle und filtern mit diesen effizienteren Tabellenkombinationstechniken.

BEARBEITEN:Ich habe diese Antwort gepostet, bevor OP das spezifische DBMS erwähnte.Es stellt sich heraus, dass SQL Server diese Abfrage NICHT so behandelt, aber möglicherweise für andere DBMS-Systeme gültig ist.Sehen Antwort von JNK für eine genauere und genauere Antwort.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top