घोषित ज्वाइन कॉलम ऑर्डर में बदलाव करना एक प्रकार का परिचय क्यों देता है?


40

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

परीक्षण सेटअप

सेटअप स्क्रिप्ट, कुछ यथार्थवादी आँकड़े सहित:

DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;

CREATE TABLE #left (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE UNIQUE CLUSTERED INDEX IX ON #left (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #left WITH ROWCOUNT=63800000, PAGECOUNT=186000;

CREATE TABLE #right (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE CLUSTERED INDEX IX ON #right (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #right WITH ROWCOUNT=55700000, PAGECOUNT=128000;

तिरस्कार

जब मैं इन दोनों तालिकाओं को उनके क्लस्टरिंग कीज़ पर जोड़ता हूं, तो मुझे उम्मीद है कि एक से कई MERGE जुड़ेंगे, जैसे:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.a=r.a AND
    l.b=r.b AND
    l.c=r.c AND
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

यह क्वेरी योजना है जो मुझे चाहिए:

यह वही चीज है जो मैं चाहता हूं।

(चेतावनियों पर कभी भी ध्यान न दें, उन्हें नकली आँकड़ों के साथ करना होगा।)

हालाँकि, अगर मैं शामिल होने के आसपास स्तंभों के क्रम को बदलता हूं, जैसे:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.c=r.c AND     -- used to be third
    l.a=r.a AND     -- used to be first
    l.b=r.b AND     -- used to be second
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

... ऐसा होता है:

जुड़ने में घोषित कॉलम क्रम को बदलने के बाद क्वेरी योजना।

सॉर्ट ऑपरेटर जॉइन के घोषित आदेश के अनुसार धाराओं को क्रमबद्ध करता है, अर्थात c, a, b, d, e, f, g, h, जो मेरी क्वेरी योजना के लिए एक अवरुद्ध ऑपरेशन जोड़ता है।

चीजें जो मैंने देखी हैं

  • मैंने NOT NULLउसी परिणाम में कॉलम बदलने की कोशिश की है ।
  • मूल तालिका के साथ बनाया गया था ANSI_PADDING OFF, लेकिन इसे बनाने से यह ANSI_PADDING ONयोजना प्रभावित नहीं होती है।
  • मैंने INNER JOINबदले की कोशिश की LEFT JOIN, कोई बदलाव नहीं हुआ।
  • मैंने इसे 2014 के SP2 एंटरप्राइज़ पर खोजा, 2017 डेवलपर (वर्तमान CU) पर एक रिप्रो बनाया।
  • प्रमुख सूचकांक कॉलम पर WHERE क्लॉज हटाने से अच्छी योजना बनती है, लेकिन यह परिणामों को प्रभावित करती है .. :)

अंत में, हम प्रश्न पर पहुँचते हैं

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

जवाबों:


28

क्या यह जानबूझकर है?

यह डिजाइन द्वारा है, हाँ। इस दावे के लिए सबसे अच्छा सार्वजनिक स्रोत दुर्भाग्य से खो गया जब Microsoft ने SQL सर्वर टीम पर डेवलपर्स से कई उपयोगी टिप्पणियों को हटाते हुए कनेक्ट फीडबैक साइट को रिटायर किया।

वैसे भी, वर्तमान ऑप्टिमाइज़र डिज़ाइन सक्रिय रूप से प्रति से अनावश्यक प्रकार से बचने की तलाश नहीं करता है । यह सबसे अधिक बार विंडोिंग फ़ंक्शन और पसंद के साथ सामना किया जाता है, लेकिन अन्य ऑपरेटरों के साथ भी देखा जा सकता है जो ऑर्डर करने के लिए संवेदनशील हैं, और विशेष रूप से ऑपरेटरों के बीच संरक्षित ऑर्डर करने के लिए।

फिर भी, अनावश्यक छँटाई से बचने के लिए ऑप्टिमाइज़र काफी अच्छा है (कई मामलों में), लेकिन यह परिणाम सामान्य रूप से आक्रामक रूप से अलग-अलग ऑर्डरिंग संयोजनों की कोशिश करने के अलावा अन्य कारणों से होता है। इस अर्थ में, यह 'खोज स्थान' का इतना सवाल नहीं है क्योंकि यह ऑर्थोगोनल ऑप्टिमाइज़र सुविधाओं के बीच जटिल बातचीत का है जो स्वीकार्य लागत पर सामान्य योजना की गुणवत्ता को बढ़ाने के लिए दिखाया गया है।

उदाहरण के लिए, छँटाई अक्सर ORDER BYएक मौजूदा सूचकांक के लिए एक आदेश की आवश्यकता (जैसे शीर्ष स्तर ) के मिलान से बचा जा सकता है । आपके मामले में तुच्छ रूप से, जिसका अर्थ हो सकता है जोड़ना ORDER BY l.a, l.b, l.c, l.d, l.e, l.f, l.g, l.h;लेकिन यह अति-सरलीकरण है (और अस्वीकार्य है क्योंकि आप क्वेरी को बदलना नहीं चाहते हैं)।

अधिक सामान्यतः, प्रत्येक मेमो समूह आवश्यक या वांछित गुणों से जुड़ा हो सकता है, जिसमें इनपुट ऑर्डर शामिल हो सकते हैं। जब किसी विशेष आदेश को लागू करने का कोई स्पष्ट कारण नहीं होता है (जैसे एक को संतुष्ट ORDER BYकरने के लिए, या एक आदेश-संवेदनशील भौतिक ऑपरेटर से सही परिणाम सुनिश्चित करने के लिए), इसमें 'भाग्य' का एक तत्व शामिल होता है। मैंने इसके बारे में और अधिक लिखा है कि यह मर्ज ज्वाइन कॉन्टैकटेशन के साथ टालने वाले सॉर्ट्स में (यूनियन या ज्वाइन मोड में) मर्ज करने से संबंधित है । इसमें से अधिकांश उत्पाद के समर्थित सतह क्षेत्र से आगे निकल जाता है, इसलिए इसे सूचनात्मक मानें, और परिवर्तन के अधीन रहें।

अपने विशेष मामले में, हाँ, आप अनुक्रमण को समायोजित कर सकते हैं क्योंकि jadarnel27 प्रकार से बचने का सुझाव देता है; हालांकि वास्तव में एक मर्ज जॉइन को तरजीह देने का कोई कारण नहीं है। आप OPTION(HASH JOIN, LOOP JOIN)डेटा के अपने ज्ञान, और सबसे अच्छे, सबसे खराब और औसत-मामले के प्रदर्शन के बीच व्यापार के आधार पर, क्वेरी को बदले बिना किसी प्लान गाइड का उपयोग करने के साथ हैश या लूप फिजिकल जॉइन में शामिल होने का संकेत दे सकते हैं ।

अंत में, एक जिज्ञासा के रूप में, ध्यान दें कि एक साधारण के साथ छंटनी से बचा जा सकता है ORDER BY l.b, एक संभावित कम कुशल की कीमत पर कई-से-कई मर्ज bअकेले में शामिल होते हैं, एक जटिल अवशिष्ट के साथ। मैं इसका उल्लेख ज्यादातर उन अनुकूलन सुविधाओं के बीच बातचीत के चित्रण के रूप में करता हूं, जिनका मैंने पहले उल्लेख किया था, और जिस तरह से शीर्ष स्तर की आवश्यकताएं प्रचारित हो सकती हैं।


19

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

यदि आप इंडेक्स को बदल सकते हैं, तो इंडेक्स #rightके ऑर्डर को ज्वाइन में फिल्टर के ऑर्डर से मिलान करने के लिए बदलकर सॉर्ट (मेरे लिए) निकालता है:

CREATE CLUSTERED INDEX IX ON #right (c, a, b, d, e, f, g, h)

आश्चर्यजनक रूप से (मेरे लिए, कम से कम), इसके परिणामस्वरूप न तो क्वेरी एक तरह से समाप्त हो रही है।

क्या यह जानबूझकर है?

कुछ अजीब ट्रेस झंडे से आउटपुट को देखते हुए , अंतिम मेमो संरचना में एक दिलचस्प अंतर है:

प्रत्येक क्वेरी के लिए अंतिम ज्ञापन संरचना का स्क्रीनशॉट

जैसा कि आप शीर्ष पर "रूट ग्रुप" में देख सकते हैं, दोनों क्वेरी में इस क्वेरी को निष्पादित करने के लिए मुख्य भौतिक ऑपरेशन के रूप में मर्ज ज्वाइन का उपयोग करने का विकल्प है।

अच्छी क्वेरी

सॉर्ट के बिना ज्वाइन समूह 29 विकल्प 1 और समूह 31 विकल्प 1 (जिनमें से प्रत्येक श्रेणी स्कैन में शामिल अनुक्रमित हैं) द्वारा संचालित है। यह समूह 27 (नहीं दिखाया गया) द्वारा फ़िल्टर किया गया है, जो तार्किक तुलना संचालन की श्रृंखला है जो जुड़ने को फ़िल्टर करता है।

बुरी क्वेरी

एक साथ तरह (नया) विकल्प 3 उन दो समूहों (29 और 31) में से प्रत्येक है से प्रेरित है। विकल्प 3 पूर्व में उल्लिखित रेंज स्कैन के परिणामों पर एक भौतिक प्रकार करता है (उन समूहों में से प्रत्येक का विकल्प 1)।

क्यूं कर?

किसी कारण से, मर्ज जॉइन के लिए स्रोतों के रूप में सीधे 29.1 और 31.1 का उपयोग करने का विकल्प भी दूसरी क्वेरी में ऑप्टिमाइज़र के लिए उपलब्ध नहीं है। अन्यथा, मुझे लगता है कि इसे अन्य विकल्पों के बीच रूट समूह के तहत सूचीबद्ध किया जाएगा। यदि यह सभी उपलब्ध थे, तो यह निश्चित रूप से बड़े पैमाने पर अधिक महंगी सॉर्ट ऑपरेशनों को उठाएगा।

मैं केवल यह निष्कर्ष निकाल सकता हूं:

  • ऑप्टिमाइज़र के खोज एल्गोरिथ्म में यह एक बग (या अधिक संभावना सीमा) है
    • केवल 5 कुंजियों को अनुक्रमणिका और जोड़ में बदलने से दूसरी क्वेरी (6, 7, और 8 कुंजियाँ सभी सॉर्ट के लिए) सॉर्ट हटा देती हैं।
    • इसका तात्पर्य यह है कि 8 कुंजियों के साथ खोज स्थान इतना बड़ा है कि अनुकूलनकर्ता के पास व्यवहार्य विकल्प के रूप में गैर-सॉर्ट समाधान की पहचान करने का समय नहीं है इससे पहले कि वह "अच्छा पर्याप्त योजना पाया" कारण से जल्दी समाप्त हो जाए
    • यह मुझे थोड़ा छोटा लगता है कि ज्वाइन की गई शर्तों का क्रम ऑप्टिमाइज़र की खोज प्रक्रिया को बहुत प्रभावित करता है, लेकिन वास्तव में यह मेरे सिर के लिए थोड़ा सा है
  • परिणामों में शुद्धता सुनिश्चित करने के लिए सॉर्ट की आवश्यकता होती है
    • यह एक संभावना नहीं लगती है, क्योंकि कम कुंजियाँ होने पर क्वेरी बिना किसी प्रकार के चल सकती है , या कुंजियाँ एक अलग क्रम में निर्दिष्ट होती हैं

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


1
मेरा मानना ​​है कि खोज स्थान के बारे में आपकी टिप्पणी वास्तव में यहाँ है। केवल अनुक्रमित का उपयोग करने के लिए, अनुकूलक को यह सत्यापित करना होगा कि वे शर्तों के लिए पर्याप्त हैं, पिछली 5 कुंजियों को वापस गिरने से पहले जांचने की बहुत अधिक संभावनाएं हैं। मुझे उत्सुकता होगी, यदि क्वेरी के सभी आदेश संयोजनों की गणना की गई थी, तो कितने अनुकूलक वापस गिरने पर सफल होंगे
Mr.Mindor

और हाँ असंगति थोड़ी छोटी लगती है, लेकिन यह संभवत: अनुक्रमित करने के लिए उपयोग किए जाने वाले एल्गोरिदम पर पूरी तरह से निर्भर है जो पर्याप्त है। यदि सभी संयोजनों का परीक्षण किया गया था, तो आप शायद परिणामों में पैटर्न देख पाएंगे और निर्धारित करेंगे कि एल्गोरिथ्म का उपयोग क्या है। मुझे यकीन है कि यह अधिक विशिष्ट उपयोग के मामलों के लिए बेहतर प्रदर्शन करने के लिए लिखा गया है। एक विकल्प मौजूद हो सकता है जो समय सीमा के भीतर 8 कुंजी समाधान को मज़बूती से खोजने में सक्षम होगा, लेकिन यह वर्तमान समाधान की तुलना में धीमा है जब 3-4 कुंजियाँ कम होती हैं।
मि। मिंडोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.