8

मैं माइक्रोसॉफ्ट एसक्यूएल सर्वर 2008 (एसपी 1, एक्स 64) का उपयोग करता हूं। मेरे पास दो प्रश्न हैं जो वही करते हैं, या इसलिए मुझे लगता है, लेकिन उनके पास पूरी तरह से अलग-अलग क्वेरी योजनाएं और प्रदर्शन हैं।OR का उपयोग कर इन टी-एसक्यूएल प्रश्नों के बीच क्या अंतर है?

क्वेरी 1:

SELECT c_pk 
FROM table_c 
WHERE c_b_id IN (SELECT b_id FROM table_b WHERE b_z = 1) 
    OR c_a_id IN (SELECT a_id FROM table_a WHERE a_z = 1) 

क्वेरी 2:

SELECT c_pk 
FROM table_c 
LEFT JOIN (SELECT b_id FROM table_b WHERE b_z = 1) AS b ON c_b_id = b_id 
LEFT JOIN (SELECT a_id FROM table_a WHERE a_z = 1) AS a ON c_a_id = a_id 
WHERE b_id IS NOT NULL 
    OR a_id IS NOT NULL 

क्वेरी 1 जबकि क्वेरी 2 बहुत धीमी है, जैसा कि मैंने उम्मीद करेंगे तेज है। query plans काफी अलग दिखता है।

मैं क्वेरी 2 को क्वेरी 1 के रूप में तेज़ करना चाहता हूं। मेरे पास सॉफ़्टवेयर है जो क्वेरी 2 का उपयोग करता है, और मैं इसे क्वेरी 1 में नहीं बदल सकता। मैं डेटाबेस बदल सकता हूं।

कुछ सवाल:

  • क्यों क्वेरी अलग योजना बना रही है कर रहे हैं?
  • क्या मैं SQL सर्वर को "सिखा सकता हूं" कि क्वेरी 2 क्वेरी 1 के बराबर है?

सभी तालिकाओं (क्लस्टर) है प्राथमिक कुंजी और उचित अनुक्रमित सभी स्तंभों पर:

CREATE TABLE table_a (
    a_pk int NOT NULL PRIMARY KEY, 
    a_id int NOT NULL UNIQUE, 
    a_z int 
) 
GO 
CREATE INDEX IX_table_a_z ON table_a (a_z) 
GO 

CREATE TABLE table_b (
    b_pk int NOT NULL PRIMARY KEY, 
    b_id int NOT NULL UNIQUE, 
    b_z int 
) 
GO 
CREATE INDEX IX_table_b_z ON table_b (b_z) 
GO 

CREATE TABLE table_c (
    c_pk int NOT NULL PRIMARY KEY, 
    c_a_id int, 
    c_b_id int 
) 
GO 
CREATE INDEX IX_table_c_a_id ON table_c (c_a_id) 
GO 
CREATE INDEX IX_table_c_b_id ON table_c (c_b_id) 
GO 

टेबल शुरू में भरने के बाद संशोधित नहीं कर रहे हैं। मैं केवल उनसे पूछताछ कर रहा हूं। उनमें लाखों रिकॉर्ड हैं (table_a: 5M, table_b: 4M, table_c: 12M), लेकिन केवल 1% का उपयोग करने से समान परिणाम मिलते हैं।

संपादित करें: मैं c_a_id और c_b_id के लिए विदेशी कुंजी जोड़ने की कोशिश की है, लेकिन मुझे आशा है कि केवल बनाया क्वेरी 1 धीमी ...

किसी query plans पर एक नजर है और अंतर की व्याख्या कर सकते हैं।

+0

इसके लिए प्रेरणा क्या है? 'IN/EXISTS' आमतौर पर SQL सर्वर में 'बाहरी जॉइन ... NULL' से अधिक कुशल है और पहली क्वेरी मेरे लिए स्पष्ट प्रतीत होती है तो क्यों न केवल पहले का उपयोग करें? –

+2

@ मार्टिन "मेरे पास सॉफ़्टवेयर है जो क्वेरी 2 का उपयोग करता है, और मैं इसे बदल नहीं सकता" –

+0

सामान्य रूप से प्रश्न समान नहीं होते हैं क्योंकि जॉइन डुप्लिकेट पंक्तियों में ला सकता है जबकि अर्द्ध शामिल नहीं होता है। यद्यपि आपने जांच नहीं की है, यदि आपके पास कोई बाधा है जो अभी तक इसे रोकती है। –

उत्तर

1

शामिल हों धीमे हैं, मुझे डिजाइन द्वारा बताएं। पहली क्वेरी रिकॉर्ड को फ़िल्टर करने के लिए उप-क्वेरी (कैशेबल) का उपयोग करती है ताकि यह कम डेटा (और प्रत्येक तालिका में कम पहुंच) उत्पन्न करे।

आप पढ़ी इन:

क्या मेरा मतलब है कि डीबी में साथ बेहतर अनुकूलन डुप्लिकेट हटाने की तरह कर सकते हैं, पहले मैच में बंद करो और है इसी तरह (और ये स्कूल यादें हैं इसलिए मुझे यकीन है कि यह बहुत बेहतर होगा)। तो मैं अनुमान सवाल यह नहीं है कि क्यूपी अलग क्यों है लेकिन कितना गहरा अनुकूलन जा सकता है।

+1

'IN' एक अर्द्ध शामिल है। सुनिश्चित नहीं है कि कैशबल उप क्वेरी द्वारा आपका क्या मतलब है। –

+0

SQL सर्वर जॉइन के साथ-साथ उप-प्रश्नों को अनुकूलित करने में काफी अच्छा है, और जो भी लुकअप सबसे तेज़ है उसका उपयोग करेगा। परन्तु इस मामले में नहीं। मैं इंडेक्स को समझता हूं, मुझे नहीं लगता कि आपका लिंक कुछ भी प्रासंगिक जोड़ता है। –

+0

मेरा मतलब है कि –

0

आप गैर समकक्ष प्रश्नों की तुलना कर रहे हैं, आप भी असामान्य तरीके से बाएं शामिल होने का उपयोग कर रहे हैं।

SELECT c_pk 
FROM table_c 
WHERE Exists( 
SELECT 1 
FROM table_b 
WHERE b_z = 1 and c_b_id = b_id 
) OR Exists( 
SELECT 1 
FROM table_a 
WHERE a_z = 1 and c_a_id = a_id 
) 
+1

का अर्थ कुछ स्पष्टीकरण जोड़ा गया है यदि आप कोड, एक्सएमएल या डेटा नमूने पोस्ट करते हैं, ** कृपया ** टेक्स्ट एडिटर में उन पंक्तियों को हाइलाइट करें और संपादक टूलबार पर "कोड नमूने" बटन ('{}') पर क्लिक करें अच्छी तरह से प्रारूप और वाक्यविन्यास इसे हाइलाइट करने के लिए! –

0

जब से तुम क्वेरी नहीं बदल सकते हैं, कम से कम आप क्वेरी का सुधार कर सकते हैं: आम तौर पर अगर तुम्हारा इरादा table_c में सभी प्रविष्टियों जो या तो table_a में रिकॉर्ड जुड़ा हुआ या table_b आप का उपयोग करना चाहिए है का चयन करने के लिए था बयान से मौजूद है वातावरण।

  1. हाइलाइट आपकी क्वेरी, उस पर SSMS में राइट क्लिक करें और चुनें "डेटाबेस इंजन ट्यूनिंग सलाहकार में क्वेरी का विश्लेषण करें।"
  2. यह पता लगाने के लिए विश्लेषण चलाएं कि क्या आपको कोई अतिरिक्त इंडेक्स या निर्मित आंकड़े चाहिए।
  3. हेड एसक्यूएल सर्वर की सलाह।
+0

मुझे अपने एसएसएमएस में कोई भी "ट्यूनिंग सलाहकार" नहीं दिख रहा है। अनुमानित निष्पादन योजना में कोई लापता इंडेक्स नहीं दिखाया गया था। सभी कॉलम पहले ही अनुक्रमित हैं, आपको क्या लगता है कि जोड़ने के लिए क्या है? –

+1

@MicheldeRuiter - संदेह है कि आप जो भी जोड़ सकते हैं। आपको क्वेरी को फिर से लिखना होगा या प्रदर्शन के साथ रहना होगा। एसक्यूएल सर्वर इस मामले में 'OR' को 'यूनियन' में परिवर्तित करने में सक्षम नहीं लगता है, इसलिए यह 'table_c' बाहरी में सभी पंक्तियों को संसाधित कर रहा है, अन्य दो तालिकाओं में शामिल होकर अंत में फ़िल्टर कर रहा है। –

+1

आपके पास शायद मुफ्त संस्करण है जहां यह उपलब्ध नहीं है या आपने इसे इंस्टॉल नहीं किया है। – JeffO

संबंधित मुद्दे