SQL IN () बनाम या


23

मैं एक क्वेरी के साथ काम कर रहा था जो मैंने लिखा था कि WHEREकुछ का उपयोग करने के बजाय एक IN (सामान की सूची) फ़िल्टर का उपयोग करने के लिए कोड को कोड से बदलना होगा

item_desc = 'item 1'
OR item_desc = 'item 2'
OR item_desc = 'item 3'
OR item_desc = 'item 4'

उपरोक्त 15 मिनट तक चला और कुछ भी नहीं लौटा, फिर भी निम्नलिखित ने मुझे 1.5 मिनट में अपना परिणाम दिया

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

मैंने SQL में ऐसा किया था और सोच रहा था कि IN (वस्तुओं की सूची) ने इतनी तेज़ी से प्रदर्शन किया है या OR कथन।

EDIT - SQL सर्वर 2008, मैं इस जानकारी को पहले स्थान पर नहीं रखने के लिए माफी माँगता हूँ।

यहाँ ORबयानों का उपयोग करते हुए क्वेरी पूरी तरह से है:

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

धन्यवाद,


10
क्या आपने क्वेरी योजना को देखा है?

1
यह बहुत विशिष्ट कार्यान्वयन है। आप कौन सा DBMS उपयोग कर रहे हैं?
जेम्स एंडरसन

मैंने क्वेरी योजना को नहीं देखा था, मुझे नहीं पता था कि यह क्वेरी विशिष्ट थी या यदि यह वास्तव में मामला था, क्योंकि इसमें हमेशा इस तरह से काम किया जाएगा।
MCP_infiltrator

3
@MCP_infiltrator इसलिए निष्पादन योजनाएँ समतुल्य नहीं होंगी क्योंकि तर्क समतुल्य नहीं है। जब ORआप ऊपर दिए गए वास्तविक प्रश्न का उपयोग करते हैं, तो आप इंजन को शॉर्ट सर्किट की अनुमति देते हैं। WHERE A AND B OR Cअगर A और B झूठे हैं तो भी सही का मूल्यांकन करेंगे, यदि C सत्य है। यदि आप कहते हैं कि WHERE A and B OR C OR D OR E OR Fजैसा आप ऊपर करते हैं, वैसे ही किया AND जा सकता है। वास्तविक समतुल्य तर्क ORकोष्ठक में श्रृंखला को ऊपर उठाना होगा ताकि उन्हें एक सेट के रूप में माना जाए WHERE A AND (B OR C OR D OR E):। इस तरह एक INइलाज किया जाता है।
JNK

5
SQL सर्वर में ऑपरेटर की पूर्वनिर्धारितता निर्दिष्ट की गई है जो ANDपहले संभाला गया है OR, इसलिए ऊपर आपकी क्वेरी समान है, 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'जिसका अर्थ है कि यदि अंतिम 3 शर्तों में से कोई भी सत्य है, तो यह शेष मूल्यांकन को शॉर्ट सर्किट करने में सक्षम होगा।
JNK

जवाबों:


28

ओलेस्की का जवाब गलत है। SQL सर्वर 2008 के लिए, एक INसूची ORबयानों की एक श्रृंखला के लिए फिर से सक्रिय हो जाती है । इसे MySQL कहना अलग हो सकता है।

मुझे पूरा यकीन है कि यदि आप अपने दोनों प्रश्नों के लिए वास्तविक निष्पादन योजनाएं बनाते हैं तो वे समान होंगे।

सभी संभावना में दूसरी क्वेरी तेजी से भागती है क्योंकि आप इसे दूसरा चलाते हैं , और पहली क्वेरी ने पहले ही डेटाबेस से सभी डेटा पृष्ठों को खींच लिया था और आईओ लागत का भुगतान किया था। दूसरी क्वेरी मेमोरी से सभी डेटा को पढ़ने और बहुत तेज़ी से निष्पादित करने में सक्षम थी।

अद्यतन करें

प्रसरण का वास्तविक स्रोत संभावना है कि प्रश्न समतुल्य नहीं हैं । आपके पास ORनीचे दो अलग-अलग सूचियाँ हैं:

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'

और बादमें

 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'

उन दोनों WHEREखंडों में, ऑपरेटर की प्राथमिकता (जहां OR से पहले संभाला जाता है) का अर्थ है कि इंजन द्वारा चलाया जाने वाला वास्तविक तर्क है:

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

यदि आप ORसूचियों को INअभिव्यक्ति के साथ बदलते हैं , तो तर्क यह होगा:

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

जो मौलिक रूप से अलग है।


2
@MCP_infiltrator खैर यह धारणा बनाने में समस्या है :) आपको वास्तव में दोनों के लिए वास्तविक निष्पादन योजनाएं मिलनी चाहिए और देखना चाहिए कि क्या कोई अंतर है, मुझे नहीं लगता कि वहाँ होगा।
JNK

4
वैसे अगर आपके पास उन्नत DB प्रश्न है, तो आप डेटाबेस प्रशासकों से भी पूछ सकते हैं - पूर्ण प्रकटीकरण, मैं वहाँ पर एक मध्यस्थ हूं, लेकिन अगर यह एक उन्नत SQL या SQL अनुकूलन प्रश्न है, तो हमारे पास विशेषज्ञों का एक टन है, खासकर SQL सर्वर के लिए
JNK

1
मैंने सिर्फ दो निष्पादन योजनाओं को देखा और वे अलग हैं। OR स्टेटमेंट के साथ क्लस्टर्ड इंडेक्स स्कैन में 68% लागत लगती है, जहां IN स्टेटमेंट 26% है, साथ ही कम निष्पादन वाले कदम भी लगते हैं।
MCP_infiltrator

3
@MCP_infiltrator कोई ज़रूरत नहीं है, शीर्ष पर अपने मूल पोस्ट पर मेरी टिप्पणी देखें। वास्तविक क्‍वेरी में आपके क्‍लॉज में अन्‍य शर्तों के कारण INआपके ORएस के बराबर नहीं है WHERE। मूल रूप से प्रश्न अलग-अलग परिणाम देंगे।
JNK

3
@MCP_infiltrator DBA.SE पर समान प्रश्न पोस्ट करने की कोई आवश्यकता नहीं है, JNK ने इसका उत्तर दिया है (और आपको वहां भी इसी तरह के उत्तर मिलेंगे।) यदि आप इसे वहां स्थानांतरित करना चाहते हैं ("माइग्रेट") हालांकि, आप इसे हमेशा ध्वजांकित कर सकते हैं। (आपका सवाल) आप क्या चाहते हैं कमेंट बॉक्स में उल्लेख करें। मॉड्स ध्यान रखेंगे।
ypercube y

7

सबसे अच्छा तरीका यह है कि वास्तविक क्वेरी प्लान को कुछ इस तरह से देखें EXPLAIN। यह आपको वास्तव में बताएगा कि DBMS क्या कर रहा है, और फिर आप अधिक बेहतर विचार प्राप्त कर सकते हैं कि यह अधिक कुशल क्यों है।

उस ने कहा, DBMS सिस्टम वास्तव में दो तालिकाओं (जैसे जॉन्स) के बीच संचालन करने में अच्छे हैं। ऑप्टिमाइज़र का बहुत समय प्रश्नों के इन भागों पर व्यतीत होता है क्योंकि वे आम तौर पर अधिक महंगे होते हैं।

उदाहरण के लिए, डीबीएमएस उस INसूची को क्रमबद्ध कर सकता है और, एक सूचकांक का उपयोग करके item_desc, परिणामों को बहुत तेज़ी से फ़िल्टर करता है। जब आप पहले उदाहरण में चयनों का एक समूह सूचीबद्ध करते हैं तो आप उस अनुकूलन को नहीं कर सकते।

जब आप उपयोग करते हैं IN, तो आप इन अधिक कुशल तालिका संयोजन तकनीकों का उपयोग करके एक इंप्रोमेप्टू टेबल और फ़िल्टरिंग कर रहे हैं।

EDIT : ओपी द्वारा विशिष्ट DBMS का उल्लेख करने से पहले मैंने यह उत्तर पोस्ट किया था। यह पता चलता है कि SQL सर्वर इस क्वेरी के साथ कैसा व्यवहार करता है, लेकिन यह अन्य DBMS सिस्टम के लिए मान्य हो सकता है। अधिक विशिष्ट, सटीक उत्तर के लिए जेएनके का उत्तर देखें ।


मुझे लगता है कि कार्डिनैलिटी का इससे बहुत कुछ लेना-देना है। यह INइतनी तेजी से नहीं होता अगर यह इसमें 100 रिकॉर्ड या एक हजार के साथ एक सबसिनेट होता।
रॉबर्ट हार्वे

@RobertHarvey हाँ, यह शायद सच है, लेकिन मुझे यह उम्मीद नहीं है कि यह बहुत बुरा होगा।
ओलेक्सी

धन्यवाद @ ओलेक्सी मुझे नहीं पता था कि DBMS IN स्टेटमेंट को
इम्प्रोमाप्टू

1
-1 - एसक्यूएल सर्वर में INस्टेटमेंट को टेबल में नहीं बदला जाता है, इसे पहचान के रूप में माना जाता है OR
JNK

2
@ Katana314 अगर SQL सर्वर में एक कीवर्ड था (जो ओपी उपयोग कर रहा है) तो मैं आपसे सहमत होगा, लेकिन यह प्रासंगिक नहीं है।
JNK
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.