Database
 sql >> डेटाबेस >  >> RDS >> Database

संख्या श्रृंखला जनरेटर चुनौती समाधान - भाग 3

संख्या श्रृंखला जनरेटर चुनौती के समाधान के बारे में श्रृंखला में यह तीसरा भाग है। भाग 1 में मैंने उन समाधानों को शामिल किया है जो मक्खी पर पंक्तियाँ उत्पन्न करते हैं। भाग 2 में मैंने उन समाधानों को शामिल किया है जो एक भौतिक आधार तालिका को क्वेरी करते हैं जिसे आप पंक्तियों के साथ पूर्व-पॉप्युलेट करते हैं। इस महीने मैं एक आकर्षक तकनीक पर ध्यान केंद्रित करने जा रहा हूं जिसका उपयोग हमारी चुनौती को संभालने के लिए किया जा सकता है, लेकिन इसके अलावा इसके दिलचस्प अनुप्रयोग भी हैं। मुझे तकनीक के आधिकारिक नाम की जानकारी नहीं है, लेकिन यह अवधारणा में कुछ हद तक क्षैतिज विभाजन उन्मूलन के समान है, इसलिए मैं इसे अनौपचारिक रूप से क्षैतिज इकाई उन्मूलन के रूप में संदर्भित करूंगा। तकनीक। तकनीक में दिलचस्प सकारात्मक प्रदर्शन लाभ हो सकते हैं, लेकिन ऐसी चेतावनी भी हैं जिनसे आपको अवगत होने की आवश्यकता है, जहां कुछ शर्तों के तहत यह प्रदर्शन जुर्माना लगा सकता है।

अपने विचारों और टिप्पणियों को साझा करने के लिए एलन बर्स्टीन, जो ओबिश, एडम मचानिक, क्रिस्टोफर फोर्ड, जेफ मोडन, चार्ली, नोएमजीआर, कामिल कोस्नो, डेव मेसन, जॉन नेल्सन #2, एड वैगनर, माइकल बरबी और पॉल व्हाइट को फिर से धन्यवाद।

मैं अपना परीक्षण tempdb में करूँगा, जिससे समय के आँकड़े सक्षम होंगे:

नोकाउंट चालू करें; टेम्पर्ड का उपयोग करें; सांख्यिकी समय चालू करें;

पहले के विचार

क्षैतिज इकाई उन्मूलन तकनीक का उपयोग स्तंभ उन्मूलन तर्क, या ऊर्ध्वाधर इकाई उन्मूलन के विकल्प के रूप में किया जा सकता है तकनीक, जिस पर मैंने पहले कवर किए गए कई समाधानों पर भरोसा किया। आप टेबल एक्सप्रेशन के साथ कॉलम एलिमिनेशन लॉजिक के बुनियादी सिद्धांतों के बारे में पढ़ सकते हैं।

वर्टिकल यूनिट एलिमिनेशन तकनीक का मूल विचार यह है कि यदि आपके पास नेस्टेड टेबल एक्सप्रेशन है जो कॉलम x और y देता है, और आपकी बाहरी क्वेरी केवल कॉलम x को संदर्भित करती है, तो क्वेरी संकलन प्रक्रिया प्रारंभिक क्वेरी ट्री से y को हटा देती है, और इसलिए योजना इसका मूल्यांकन करने की आवश्यकता नहीं है। इसके कई सकारात्मक अनुकूलन-संबंधी निहितार्थ हैं, जैसे कि अकेले x के साथ सूचकांक कवरेज प्राप्त करना, और यदि y एक गणना का परिणाम है, तो y की अंतर्निहित अभिव्यक्ति का मूल्यांकन करने की बिल्कुल भी आवश्यकता नहीं है। यह विचार एलन बर्स्टीन के समाधान के केंद्र में था। मैंने कई अन्य समाधानों में भी इस पर भरोसा किया, जैसे कि dbo.GetNumsAlanCharlieItzikBatch (भाग 1 से), फ़ंक्शन dbo.GetNumsJohn2DaveObbishAlanCharlieItzik और dbo.GetNumsJohn2DaveObbishAlanCharlieItzik2 के साथ, और अन्य (भाग 2 से)। एक उदाहरण के रूप में, मैं dbo.GetNumsAlanCharlieItzikBatch का उपयोग ऊर्ध्वाधर उन्मूलन तर्क के साथ आधारभूत समाधान के रूप में करूँगा।

एक अनुस्मारक के रूप में, यह समाधान एक डमी टेबल के साथ जुड़ने का उपयोग करता है जिसमें बैच प्रोसेसिंग प्राप्त करने के लिए कॉलमस्टोर इंडेक्स होता है। यहाँ डमी टेबल बनाने के लिए कोड दिया गया है:

ड्रॉप टेबल अगर मौजूद है dbo.BatchMe;GO CREATE TABLE dbo.BatchMe(col1 INT NOT NULL, INDEX idx_cs CLUSTERED COLUMNSTORE);

और यहां dbo.GetNumsAlanCharlieItzikBatch फ़ंक्शन की परिभाषा वाला कोड दिया गया है:

 क्रिएट या अल्टर फंक्शन dbo.GetNumsAlanCharlieItzikBatch(@low AS BIGINT =1, @high AS BIGINT) L0 AS के साथ TABLEASRETURN लौटाता है (से 1 AS c चुनें (VALUES(1),(1),(1),(1) ),(1),(1),(1),(1), (1),(1),(1),(1),(1),(1),(1),(1)) एएस डी (सी)), एल 1 एएस (एक क्रॉस जॉइन एल 0 एएस बी के रूप में एल 0 से सी चुनें), एल 2 एएस (एल 1 से एक क्रॉस जॉइन एल 1 एएस बी के रूप में चुनें), एल 3 एएस (चुनें 1 एएस सी चुनें) L2 से एक क्रॉस जॉइन L2 AS B के रूप में), नंबर्स AS (सिलेक्ट ROW_NUMBER() ओवर (ऑर्डर बाय (सिलेक्ट NULL)) AS Rownum L3 से) सेलेक्ट टॉप (@high - @low + 1) rownum AS rn, @high + 1 - राउनम एएस ऑप, @लो - 1 + राउनम एएस एन फ्रॉम नंबर्स लेफ्ट आउटर जॉइन dbo.BatchMe ON 1 =0 Rownum द्वारा ऑर्डर करें;GO

मैंने 100M पंक्तियों के साथ फ़ंक्शन के प्रदर्शन का परीक्षण करने के लिए निम्नलिखित कोड का उपयोग किया, गणना परिणाम कॉलम n (ROW_NUMBER फ़ंक्शन के परिणाम में हेरफेर), n द्वारा आदेश दिया गया:

घोषित @n के रूप में BIGINT; dbo से @n =n चुनें। 

यहाँ समय के आँकड़े हैं जो मुझे इस परीक्षा के लिए मिले हैं:

सीपीयू समय =9328 एमएस, बीता हुआ समय =9330 एमएस।

मैंने 100M पंक्तियों के साथ फ़ंक्शन के प्रदर्शन का परीक्षण करने के लिए निम्न कोड का उपयोग किया, कॉलम rn लौटाया (प्रत्यक्ष, अप्रबंधित, ROW_NUMBER फ़ंक्शन का परिणाम), rn द्वारा आदेश दिया गया:

घोषित @n के रूप में BIGINT; dbo से @n =rn चुनें। 

यहाँ समय के आँकड़े हैं जो मुझे इस परीक्षा के लिए मिले हैं:

सीपीयू समय =7296 एमएस, बीता हुआ समय =7291 एमएस।

आइए उन महत्वपूर्ण विचारों की समीक्षा करें जो इस समाधान में अंतर्निहित हैं।

कॉलम एलिमिनेशन लॉजिक पर भरोसा करते हुए, एलन नंबर सीरीज़ के साथ न केवल एक कॉलम लौटाने का विचार लेकर आया, बल्कि तीन:

  • कॉलम rn ROW_NUMBER फ़ंक्शन के एक अप्रबंधित परिणाम का प्रतिनिधित्व करता है, जो 1 से शुरू होता है। यह गणना करने के लिए सस्ता है। जब आप स्थिरांक प्रदान करते हैं और जब आप फ़ंक्शन के इनपुट के रूप में गैर-स्थिरांक (चर, कॉलम) प्रदान करते हैं तो यह दोनों को संरक्षित करने का आदेश है। इसका मतलब यह है कि जब आपकी बाहरी क्वेरी ORDER BY rn का उपयोग करती है, तो आपको योजना में एक सॉर्ट ऑपरेटर नहीं मिलता है।
  • कॉलम n @low, एक स्थिरांक और राउनम (ROW_NUMBER फ़ंक्शन का परिणाम) के आधार पर गणना का प्रतिनिधित्व करता है। जब आप फ़ंक्शन में इनपुट के रूप में स्थिरांक प्रदान करते हैं, तो यह राउनम के संबंध में संरक्षित करने का क्रम है। निरंतर तह के बारे में चार्ली की अंतर्दृष्टि के लिए धन्यवाद (विवरण के लिए भाग 1 देखें)। हालाँकि, जब आप इनपुट के रूप में गैर-स्थिरांक प्रदान करते हैं, तो यह संरक्षित करने का आदेश नहीं है, क्योंकि आपको निरंतर तह नहीं मिलती है। मैं इसे बाद में चेतावनियों के बारे में अनुभाग में प्रदर्शित करूँगा।
  • कॉलम ऑप विपरीत क्रम में n का प्रतिनिधित्व करता है। यह एक गणना का परिणाम है और यह संरक्षित करने का आदेश नहीं है।

कॉलम एलिमिनेशन लॉजिक पर भरोसा करते हुए, यदि आपको 1 से शुरू होने वाली संख्या श्रृंखला वापस करने की आवश्यकता है, तो आप कॉलम rn को क्वेरी करते हैं, जो कि n को क्वेरी करने से सस्ता है। यदि आपको 1 के अलावा किसी अन्य मान से शुरू होने वाली संख्या श्रृंखला की आवश्यकता है, तो आप n से पूछताछ करते हैं और अतिरिक्त लागत का भुगतान करते हैं। यदि आपको संख्या कॉलम द्वारा आदेशित परिणाम की आवश्यकता है, तो स्थिरांक के साथ इनपुट के रूप में आप ORDER BY rn या ORDER BY n का उपयोग कर सकते हैं। लेकिन इनपुट के रूप में गैर-स्थिरांक के साथ, आप ORDER BY rn का उपयोग करना सुनिश्चित करना चाहते हैं। यह एक अच्छा विचार हो सकता है कि हमेशा ORDER BY rn का उपयोग करने के लिए बने रहें जब परिणाम सुरक्षित पक्ष पर होने के आदेश की आवश्यकता हो।

क्षैतिज इकाई उन्मूलन विचार ऊर्ध्वाधर इकाई उन्मूलन विचार के समान है, केवल यह स्तंभों के सेट के बजाय पंक्तियों के सेट पर लागू होता है। वास्तव में, जो ओबिश ने अपने कार्य dbo.GetNumsObbish (भाग 2 से) में इस विचार पर भरोसा किया, और हम इसे एक कदम आगे ले जाएंगे। अपने समाधान में, जो ने उपश्रेणी की प्रयोज्यता को परिभाषित करने के लिए प्रत्येक क्वेरी के WHERE क्लॉज में एक फिल्टर का उपयोग करते हुए, संख्याओं के असंबद्ध उप-श्रेणियों का प्रतिनिधित्व करने वाले कई प्रश्नों को एकीकृत किया। जब आप फ़ंक्शन को कॉल करते हैं और अपनी वांछित सीमा के सीमांकक का प्रतिनिधित्व करने वाले निरंतर इनपुट पास करते हैं, तो SQL सर्वर संकलन समय पर अनुपयुक्त प्रश्नों को समाप्त कर देता है, इसलिए योजना उन्हें प्रतिबिंबित भी नहीं करती है।

क्षैतिज इकाई उन्मूलन, संकलन समय बनाम रन टाइम

शायद अधिक सामान्य मामले में क्षैतिज इकाई उन्मूलन की अवधारणा का प्रदर्शन करके शुरू करना एक अच्छा विचार होगा, और संकलन-समय और रन-टाइम उन्मूलन के बीच एक महत्वपूर्ण अंतर पर भी चर्चा करें। फिर हम चर्चा कर सकते हैं कि इस विचार को हमारी संख्या श्रृंखला चुनौती पर कैसे लागू किया जाए।

मैं अपने उदाहरण में dbo.T1, dbo.T2 और dbo.T3 नामक तीन तालिकाओं का उपयोग करूंगा। इन तालिकाओं को बनाने और भरने के लिए निम्नलिखित डीडीएल और डीएमएल कोड का उपयोग करें:

ड्रॉप टेबल अगर मौजूद है dbo.T1, dbo.T2, dbo.T3; GO CREATE TABLE dbo.T1(col1 INT); dbo.T1 (col1) Values ​​(1) में सम्मिलित करें; तालिका बनाएं dbo.T2 (col1 INT); dbo.T2(col1) VALUES(2) में सम्मिलित करें; तालिका बनाएं dbo.T3 (col1 INT); dbo.T3(col1) VALUES(3) में डालें;

मान लीजिए कि आप dbo.OneTable नामक एक इनलाइन TVF लागू करना चाहते हैं जो उपरोक्त तीन तालिका नामों में से एक को इनपुट के रूप में स्वीकार करता है, और अनुरोधित तालिका से डेटा लौटाता है। क्षैतिज इकाई उन्मूलन अवधारणा के आधार पर, आप फ़ंक्शन को इस प्रकार कार्यान्वित कर सकते हैं:

dbo.OneTable(@WhichTable AS NVARCHAR(257)) के रूप में
बनाएं या बदलें 'dbo.T2' यूनियन सभी dbo.T3 से col1 चुनें जहां @WhichTable =N'dbo.T3';GO

याद रखें कि एक इनलाइन टीवीएफ पैरामीटर एम्बेडिंग लागू करता है। इसका मतलब यह है कि जब आप इनपुट के रूप में N'dbo.T2' जैसे स्थिरांक को पास करते हैं, तो इनलाइनिंग प्रक्रिया @WhichTable के सभी संदर्भों को ऑप्टिमाइज़ेशन से पहले स्थिरांक से बदल देती है। . उन्मूलन प्रक्रिया तब प्रारंभिक क्वेरी ट्री से T1 और T3 के संदर्भों को हटा सकती है, और इस प्रकार क्वेरी ऑप्टिमाइज़ेशन परिणाम एक ऐसी योजना में परिणाम देता है जो केवल T2 को संदर्भित करता है। आइए निम्नलिखित प्रश्न के साथ इस विचार का परीक्षण करें:

चुनें * dbo.OneTable(N'dbo.T2');
. से

इस क्वेरी की योजना चित्र 1 में दिखाई गई है।

चित्र 1:निरंतर इनपुट के साथ dbo.OneTable के लिए योजना

जैसा कि आप देख सकते हैं, योजना में केवल तालिका T2 दिखाई देती है।

जब आप इनपुट के रूप में एक गैर-स्थिरांक पास करते हैं तो चीजें थोड़ी पेचीदा होती हैं। यह मामला तब हो सकता है जब एक चर, एक प्रक्रिया पैरामीटर का उपयोग कर रहा हो, या APPLY के माध्यम से एक कॉलम पास कर रहा हो। इनपुट मूल्य या तो संकलन समय पर अज्ञात है, या पैरामीटरयुक्त योजना पुन:उपयोग क्षमता को ध्यान में रखा जाना चाहिए।

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

DECLARE @T AS NVARCHAR(257) =N'dbo.T2'; चुनें * dbo.OneTable(@T);
. से

इस निष्पादन की योजना चित्र 2 में दिखाई गई है:

चित्र 2:गैर-स्थिर इनपुट के साथ dbo.OneTable के लिए योजना

प्लान एक्सप्लोरर यह देखने के लिए आश्चर्यजनक रूप से स्पष्ट करता है कि केवल लागू सबट्री को निष्पादित किया गया है (निष्पादन =1), और उन उपट्री को ग्रे करता है जो निष्पादित नहीं हुए (निष्पादन =0)। साथ ही, सांख्यिकी IO केवल उस तालिका के लिए I/O जानकारी दिखाता है जिसे एक्सेस किया गया था:

तालिका 'T2'। स्कैन काउंट 1, लॉजिकल रीड्स 1, फिजिकल रीड्स 0, पेज सर्वर रीड्स 0, रीड-फॉरवर्ड रीड्स 0, पेज सर्वर रीड-फॉरवर्ड रीड्स 0, लोब लॉजिकल रीड्स 0, लोब फिजिकल रीड्स 0, लोब पेज सर्वर रीड्स 0, लोब रीड- आगे 0 पढ़ता है, लोब पेज सर्वर रीड-फॉरवर्ड 0 पढ़ता है।

संख्या श्रृंखला चुनौती के लिए क्षैतिज इकाई उन्मूलन तर्क लागू करना

जैसा कि उल्लेख किया गया है, आप पहले के किसी भी समाधान को संशोधित करके क्षैतिज इकाई उन्मूलन अवधारणा को लागू कर सकते हैं जो वर्तमान में लंबवत उन्मूलन तर्क का उपयोग करते हैं। मैं अपने उदाहरण के लिए शुरुआती बिंदु के रूप में dbo.GetNumsAlanCharlieItzikBatch फ़ंक्शन का उपयोग करूंगा।

याद रखें कि जो ओबिश ने संख्या श्रृंखला के प्रासंगिक असंबद्ध उपश्रेणियों को निकालने के लिए क्षैतिज इकाई उन्मूलन का उपयोग किया था। हम कम खर्चीले गणना (आरएन) को क्षैतिज रूप से अलग करने के लिए अवधारणा का उपयोग करेंगे जहां @ कम =1 अधिक महंगी गणना (एन) से जहां @ कम <> 1.

जब हम इस पर होते हैं, हम जेफ मोडन के विचार को उनके fnTally फ़ंक्शन में जोड़कर प्रयोग कर सकते हैं, जहां वह उन मामलों के लिए मान 0 के साथ एक प्रहरी पंक्ति का उपयोग करता है जहां सीमा @low =0 से शुरू होती है।

तो हमारे पास चार क्षैतिज इकाइयाँ हैं:

  • 0 के साथ प्रहरी पंक्ति जहां @low =0, n =0 के साथ
  • TOP (@high) पंक्तियाँ जहाँ @low =0, सस्ते n =rownum के साथ, और op =@high - rownum
  • TOP (@high) पंक्तियाँ जहाँ @low =1, सस्ते n =rownum के साथ, और op =@high + 1 - rownum
  • TOP(@high - @low + 1) पंक्तियाँ जहाँ @low <> 0 और @low <> 1, अधिक महंगे n =@low - 1 + rownum, और op =@high + 1 - rownum के साथ। ली>

यह समाधान एलन, चार्ली, जो, जेफ और स्वयं के विचारों को जोड़ता है, इसलिए हम फ़ंक्शन के बैच-मोड संस्करण को dbo.GetNumsAlanCharlieJoeJeffItzikBatch कहते हैं।

सबसे पहले, यह सुनिश्चित करना याद रखें कि हमारे समाधान में बैच प्रोसेसिंग प्राप्त करने के लिए आपके पास अभी भी डमी टेबल dbo.BatchMe मौजूद है, या यदि आप नहीं करते हैं तो निम्न कोड का उपयोग करें:

ड्रॉप टेबल अगर मौजूद है dbo.BatchMe;GO CREATE TABLE dbo.BatchMe(col1 INT NOT NULL, INDEX idx_cs CLUSTERED COLUMNSTORE);

यहाँ dbo.GetNumsAlanCharlieJoeJeffItzikBatch फ़ंक्शन की परिभाषा के साथ कोड दिया गया है:

 क्रिएट या अल्टर फंक्शन dbo.GetNumsAlanCharlieJoeJeffItzikBatch(@low AS BIGINT =1, @high AS BIGINT) L0 AS के साथ TABLEASRETURN लौटाता है (से 1 AS c चुनें (VALUES(1),(1),(1),(1) ),(1),(1),(1),(1), (1),(1),(1),(1),(1),(1),(1),(1)) एएस डी (सी)), एल 1 एएस (एक क्रॉस जॉइन एल 0 एएस बी के रूप में एल 0 से सी चुनें), एल 2 एएस (एल 1 से एक क्रॉस जॉइन एल 1 एएस बी के रूप में चुनें), एल 3 एएस (चुनें 1 एएस सी चुनें) L2 से क्रॉस जॉइन L2 AS B के रूप में), नंबर्स AS (सेलेक्ट ROW_NUMBER() ओवर (ऑर्डर बाय (सिलेक्ट NULL)) L3 से राउनम के रूप में) @low AS n, @high AS op जहां @low =0 और @high चुनें> @लो यूनियन ऑल सेलेक्ट टॉप (@ हाई) राउनम एएस एन, @ हाई - राउनम अस ऑप फ्रॉम नंबर्स लेफ्ट आउटर जॉइन dbo.BatchMe ऑन 1 =0 जहां @low =0 राउनम यूनियन द्वारा ऑर्डर सभी सेलेक्ट टॉप (@ हाई) राउनम एएस एन, @ हाई + 1 - रॉनम अस ऑप फ्रॉम नंबर्स लेफ्ट आउटर जॉइन dbo.BatchMe ON 1 =0 जहां @low =1 ऑर्डर बाई राउनम यूनियन सभी सिलेक्ट टॉप(@high - @low + 1) @low - 1 + Rownum एएस एन, @high + 1 - रॉनम के रूप में नंबर्स से बाएं बाहरी जॉइन dbo.BatchMe ON 1 =0 जहां @low <> 0 और @low <> 1 rownum द्वारा ऑर्डर करें;GO

महत्वपूर्ण:क्षैतिज इकाई उन्मूलन अवधारणा ऊर्ध्वाधर की तुलना में लागू करने के लिए निस्संदेह अधिक जटिल है, तो परेशान क्यों हैं? क्योंकि यह उपयोगकर्ता से सही कॉलम चुनने की जिम्मेदारी को हटा देता है। उपयोगकर्ता को केवल n नामक कॉलम को क्वेरी करने के बारे में चिंता करने की ज़रूरत है, क्योंकि rn का उपयोग करने के लिए याद रखने के विपरीत जब रेंज 1 से शुरू होती है, और n अन्यथा।

आइए निरंतर इनपुट 1 और 100,000,000 के साथ समाधान का परीक्षण करके शुरू करें, परिणाम के लिए आदेश देने के लिए कहें:

घोषित @n के रूप में BIGINT; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 3 में दिखाई गई है।

चित्र 3:dbo के लिए योजना।GetNumsAlanCharlieJoeJeffItzikBatch(1, 100M)

ध्यान दें कि केवल लौटाया गया कॉलम प्रत्यक्ष, गैर-मैनिपुलेटेड, ROW_NUMBER अभिव्यक्ति (Expr1313) पर आधारित है। यह भी देखें कि योजना में छँटाई की कोई आवश्यकता नहीं है।

मुझे इस निष्पादन के लिए निम्नलिखित समय के आँकड़े मिले:

सीपीयू समय =7359 एमएस, बीता हुआ समय =7354 एमएस।

रनटाइम पर्याप्त रूप से इस तथ्य को प्रतिबिंबित करता है कि योजना बैच मोड का उपयोग करती है, अप्रचलित ROW_NUMBER अभिव्यक्ति, और कोई छँटाई नहीं।

इसके बाद, 0 से 99,999,999 की निरंतर श्रेणी के साथ फ़ंक्शन का परीक्षण करें:

DECLARE @n AS BIGINT; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 4 में दिखाई गई है।

चित्र 4:dbo के लिए योजना। GetNumsAlanCharlieJoeJeffItzikBatch(0, 99999999)

प्रहरी पंक्ति को मान 0 और शेष के साथ मर्ज करने के लिए योजना मर्ज जॉइन (Concatenation) ऑपरेटर का उपयोग करती है। भले ही दूसरा भाग पहले की तरह ही कुशल है, मर्ज लॉजिक रन टाइम पर लगभग 26% का एक बड़ा टोल लेता है, जिसके परिणामस्वरूप निम्नलिखित समय आँकड़े होते हैं:

सीपीयू समय =9265 एमएस, बीता हुआ समय =9298 एमएस।

आइए फ़ंक्शन का परीक्षण 2 से 100,000,001 की निरंतर सीमा के साथ करें:

DECLARE @n AS BIGINT; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 5 में दिखाई गई है।

चित्र 5:dbo के लिए योजना। GetNumsAlanCharlieJoeJeffItzikBatch(2, 100000001)

इस बार कोई महंगा मर्ज तर्क नहीं है क्योंकि प्रहरी पंक्ति का हिस्सा अप्रासंगिक है। हालांकि, ध्यान दें कि लौटा हुआ कॉलम हेरफेर किया गया एक्सप्रेशन @low - 1 + Rownum है, जो पैरामीटर एम्बेडिंग / इनलाइनिंग और निरंतर फोल्डिंग के बाद 1 + राउनम बन गया।

यहाँ समय के आँकड़े हैं जो मुझे इस निष्पादन के लिए मिले हैं:

CPU समय =9000 ms, बीता हुआ समय =9015 ms.

जैसा कि अपेक्षित था, यह 1 से शुरू होने वाली श्रेणी के साथ उतना तेज़ नहीं है, लेकिन दिलचस्प है, 0 से शुरू होने वाली श्रेणी की तुलना में तेज़ है।

0 प्रहरी पंक्ति को हटाया जा रहा है

यह देखते हुए कि मूल्य 0 के साथ प्रहरी पंक्ति वाली तकनीक राउनम में हेरफेर लागू करने की तुलना में धीमी लगती है, यह केवल इससे बचने के लिए समझ में आता है। यह हमें एक सरल क्षैतिज उन्मूलन-आधारित समाधान में लाता है जो एलन, चार्ली, जो और मेरे विचारों को मिलाता है। मैं इस समाधान dbo.GetNumsAlanCharlieJoeItzikBatch के साथ फ़ंक्शन को कॉल करूंगा। यहाँ फ़ंक्शन की परिभाषा है:

 क्रिएट या अल्टर फंक्शन dbo.GetNumsAlanCharlieJoeItzikBatch(@low AS BIGINT =1, @high AS BIGINT) L0 AS के साथ TABLEASRETURN लौटाता है (से 1 AS c चुनें (VALUES(1),(1),(1),(1) ),(1),(1),(1),(1), (1),(1),(1),(1),(1),(1),(1),(1)) एएस डी (सी)), एल 1 एएस (एक क्रॉस जॉइन एल 0 एएस बी के रूप में एल 0 से सी चुनें), एल 2 एएस (एल 1 से एक क्रॉस जॉइन एल 1 एएस बी के रूप में चुनें), एल 3 एएस (चुनें 1 एएस सी चुनें) L2 से एक क्रॉस जॉइन L2 AS B के रूप में), नंबर्स AS (सेलेक्ट ROW_NUMBER() ओवर (ऑर्डर बाय (सिलेक्ट NULL)) AS Rownum L3 से) सेलेक्ट टॉप (@high) rownum AS n, @high + 1 - rownum AS op संख्या बाएं बाहरी से dbo.BatchMe पर 1 =0 पर शामिल हों जहां @low =1 पंक्तिबद्ध संघ द्वारा आदेश सभी शीर्ष चुनें (@high - @low + 1) @low - 1 + rownum AS n, @high + 1 - rownum AS op संख्याओं से बाएँ बाहरी जॉइन dbo.BatchMe ON 1 =0 जहाँ @low <> 1 rownum द्वारा ऑर्डर करें;GO

आइए 1 से 100M की सीमा के साथ इसका परीक्षण करें:

DECLARE @n AS BIGINT; dbo से @n =n चुनें। 

योजना वैसी ही है जैसी पहले चित्र 3 में दिखाई गई थी, जैसा कि अपेक्षित था।

तदनुसार, मुझे निम्नलिखित समय आँकड़े मिले:

सीपीयू समय =7219 एमएस, बीता हुआ समय =7243 एमएस।

0 से 99,999,999 की सीमा के साथ इसका परीक्षण करें:

DECLARE @n AS BIGINT; dbo से @n =n चुनें। 

इस बार आपको वही योजना मिलेगी जो पहले चित्र 5 में दिखाई गई थी—चित्र 4 नहीं।

यहाँ समय के आँकड़े हैं जो मुझे इस निष्पादन के लिए मिले हैं:

सीपीयू समय =9313 एमएस, बीता हुआ समय =9334 एमएस।

2 से 100,000,001 की सीमा के साथ इसका परीक्षण करें:

DECLARE @n AS BIGINT; dbo से @n =n चुनें। 

फिर से आपको वही प्लान मिलता है जो पहले चित्र 5 में दिखाया गया था।

मुझे इस निष्पादन के लिए निम्नलिखित समय के आँकड़े मिले:

CPU समय =9125 ms, बीता हुआ समय =9148 ms.

अस्थिर इनपुट का उपयोग करते समय चेतावनी

दोनों ऊर्ध्वाधर और क्षैतिज इकाई उन्मूलन तकनीकों के साथ, चीजें आदर्श रूप से तब तक काम करती हैं जब तक आप स्थिरांक को इनपुट के रूप में पास करते हैं। हालाँकि, आपको उन चेतावनियों से अवगत होने की आवश्यकता है जिनके परिणामस्वरूप जब आप गैर-निरंतर इनपुट पास करते हैं तो प्रदर्शन दंड हो सकता है। लंबवत इकाई उन्मूलन तकनीक में कम समस्याएं हैं, और जो समस्याएं मौजूद हैं उनका सामना करना आसान है, तो चलिए इसके साथ शुरू करते हैं।

याद रखें कि इस लेख में हमने हमारे उदाहरण के रूप में dbo.GetNumsAlanCharlieItzikBatch फ़ंक्शन का उपयोग किया है जो लंबवत इकाई उन्मूलन अवधारणा पर निर्भर करता है। आइए गैर-स्थिर इनपुट के साथ परीक्षणों की एक श्रृंखला चलाते हैं, जैसे कि चर।

हमारे पहले परीक्षण के रूप में, हम rn लौटाएंगे और rn द्वारा आदेशित डेटा मांगेंगे:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =100000000; बड़ी के रूप में @n घोषित करें; dbo से @n =rn चुनें। 

याद रखें कि rn अनियंत्रित ROW_NUMBER अभिव्यक्ति का प्रतिनिधित्व करता है, इसलिए तथ्य यह है कि हम गैर-निरंतर इनपुट का उपयोग करते हैं, इस मामले में कोई विशेष महत्व नहीं है। योजना में स्पष्ट छँटाई की कोई आवश्यकता नहीं है।

मुझे इस निष्पादन के लिए निम्नलिखित समय आँकड़े मिले:

सीपीयू समय =7390 एमएस, बीता हुआ समय =7386 एमएस।

ये संख्याएँ आदर्श स्थिति का प्रतिनिधित्व करती हैं।

अगले परीक्षण में, परिणाम पंक्तियों को n द्वारा क्रमित करें:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =100000000; बड़ी के रूप में @n घोषित करें; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 6 में दिखाई गई है।

चित्र 6:dbo के लिए योजना। GetNumsAlanCharlieItzikBatch(@mylow, @myhigh) द्वारा ऑर्डर करना एन

समस्या देखें? इनलाइनिंग के बाद, @low को @mylow के साथ प्रतिस्थापित किया गया था - @mylow में मान के साथ नहीं, जो कि 1 है। नतीजतन, निरंतर फोल्डिंग नहीं हुई, और इसलिए n राउनम के संबंध में संरक्षित करने का आदेश नहीं है। इसके परिणामस्वरूप योजना में स्पष्ट छँटाई हुई।

यहाँ समय के आँकड़े हैं जो मुझे इस निष्पादन के लिए मिले हैं:

सीपीयू समय =25141 एमएस, बीता हुआ समय =25628 एमएस।

जब स्पष्ट सॉर्टिंग की आवश्यकता नहीं थी, तो निष्पादन समय लगभग तीन गुना हो गया।

एक सरल समाधान यह है कि एलन बर्स्टीन के मूल विचार का उपयोग हमेशा rn द्वारा ऑर्डर करने के लिए किया जाता है, जब आपको ऑर्डर किए गए परिणाम की आवश्यकता होती है, दोनों rn लौटते समय और n लौटते समय, जैसे:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =100000000; बड़ी के रूप में @n घोषित करें; dbo से @n =n चुनें। 

इस बार योजना में कोई स्पष्ट छँटाई नहीं है।

मुझे इस निष्पादन के लिए निम्नलिखित समय के आँकड़े मिले:

CPU समय =9156 ms, बीता हुआ समय =9184 ms.

संख्याएं इस तथ्य को पर्याप्त रूप से दर्शाती हैं कि आप हेरफेर किए गए अभिव्यक्ति को वापस कर रहे हैं, लेकिन कोई स्पष्ट छँटाई नहीं कर रहे हैं।

हमारे dbo.GetNumsAlanCharlieJoeItzikBatch फ़ंक्शन जैसे क्षैतिज इकाई उन्मूलन तकनीक पर आधारित समाधानों के साथ, गैर-स्थिर इनपुट का उपयोग करते समय स्थिति अधिक जटिल होती है।

आइए पहले 10 संख्याओं की एक बहुत छोटी श्रेणी के साथ फ़ंक्शन का परीक्षण करें:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =10; बड़ी के रूप में @n घोषित करें; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 7 में दिखाई गई है।

चित्र 7:dbo के लिए योजना।GetNumsAlanCharlieJoeItzikBatch(@mylow, @myhigh)

इस योजना का एक बहुत ही खतरनाक पक्ष है। ध्यान दें कि फ़िल्टर ऑपरेटर नीचे दिखाई देते हैं शीर्ष ऑपरेटरों! गैर-निरंतर इनपुट वाले फ़ंक्शन को दिए गए किसी भी कॉल में, स्वाभाविक रूप से कॉन्सटेनेशन ऑपरेटर के नीचे की शाखाओं में से एक में हमेशा एक झूठी फ़िल्टर स्थिति होगी। हालांकि, दोनों शीर्ष ऑपरेटर पंक्तियों की एक गैर-शून्य संख्या मांगते हैं। तो झूठी फ़िल्टर स्थिति वाले ऑपरेटर के ऊपर शीर्ष ऑपरेटर पंक्तियों के लिए पूछेगा, और कभी भी संतुष्ट नहीं होगा क्योंकि फ़िल्टर ऑपरेटर अपने बच्चे नोड से प्राप्त सभी पंक्तियों को त्याग देगा। फ़िल्टर ऑपरेटर के नीचे सबट्री में काम पूरा होने तक चलना होगा। हमारे मामले में इसका मतलब है कि उपट्री 4B पंक्तियों को उत्पन्न करने के काम से गुजरेगी, जिसे फ़िल्टर ऑपरेटर त्याग देगा। आपको आश्चर्य है कि फ़िल्टर ऑपरेटर अपने चाइल्ड नोड से पंक्तियों का अनुरोध क्यों करता है, लेकिन ऐसा प्रतीत होता है कि यह वर्तमान में कैसे काम करता है। इसे स्थिर योजना के साथ देखना कठिन है। इसे लाइव देखना आसान है, उदाहरण के लिए, सेंट्रीऑन प्लान एक्सप्लोरर में लाइव क्वेरी निष्पादन विकल्प के साथ, जैसा कि चित्र 8 में दिखाया गया है। इसे आज़माएं।

चित्र 8:dbo.GetNumsAlanCharlieJoeItzikBatch(@mylow, @myhigh) के लिए लाइव क्वेरी सांख्यिकी

मेरी मशीन पर इस परीक्षण को पूरा करने में 9:15 मिनट का समय लगा, और याद रखें कि अनुरोध 10 नंबरों की एक श्रृंखला वापस करने का था।

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

इस ट्रिक को लागू करने वाला हमारा संशोधित कार्य है:

 क्रिएट या अल्टर फंक्शन dbo.GetNumsAlanCharlieJoeItzikBatch(@low AS BIGINT =1, @high AS BIGINT) L0 AS के साथ TABLEASRETURN लौटाता है (से 1 AS c चुनें (VALUES(1),(1),(1),(1) ),(1),(1),(1),(1), (1),(1),(1),(1),(1),(1),(1),(1)) एएस डी (सी)), एल 1 एएस (एक क्रॉस जॉइन एल 0 एएस बी के रूप में एल 0 से सी चुनें), एल 2 एएस (एल 1 से एक क्रॉस जॉइन एल 1 एएस बी के रूप में चुनें), एल 3 एएस (चुनें 1 एएस सी चुनें) L2 से एक क्रॉस जॉइन L2 AS B के रूप में), नंबर्स AS (सेलेक्ट ROW_NUMBER() ओवर (ऑर्डर बाय (सिलेक्ट NULL)) AS Rownum L3 से) सेलेक्ट करें * से (सेलेक्ट टॉप(@high) Rownum AS n, @high + 1 - पंक्ति संख्या के रूप में बाएं बाहरी से जुड़ें dbo.BatchMe पर 1 =0 पंक्तिबद्ध द्वारा आदेश) D1 के रूप में जहां @ कम =1 संघ सभी का चयन करें * से (शीर्ष चुनें (@ उच्च - @ कम + 1) @ कम - 1 + पंक्ति संख्या AS n, @high + 1 - रॉनम अस ऑप फ्रॉम नंबर्स लेफ्ट आउटर जॉइन dbo.BatchMe ON 1 =0 ORDER BY rownum ) AS D2 जहां @low <> 1;GO

जैसा कि अपेक्षित था, स्थिरांक के साथ निष्पादन बिना चाल के वैसा ही व्यवहार और प्रदर्शन करते रहते हैं।

गैर-स्थिर इनपुट के लिए, अब छोटी श्रेणियों के साथ यह बहुत तेज़ है। यहां 10 नंबरों की श्रेणी के साथ एक परीक्षण दिया गया है:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =10; बड़ी के रूप में @n घोषित करें; dbo से @n =n चुनें। 

इस निष्पादन की योजना चित्र 9 में दिखाई गई है।

चित्र 9:बेहतर dbo के लिए योजना। GetNumsAlanCharlieJoeItzikBatch(@mylow, @myhigh)

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

100M नंबरों की एक बड़ी रेंज के साथ फ़ंक्शन का परीक्षण करें:

DECLARE @mylow AS BIGINT =1, @myhigh AS BIGINT =100000000; बड़ी के रूप में @n घोषित करें; dbo से @n =n चुनें। 

मुझे निम्नलिखित समय आँकड़े मिले:

सीपीयू समय =29907 एमएस, बीता हुआ समय =29909 एमएस।

निराशाजनक; यह लगभग सही था!

प्रदर्शन सारांश और जानकारी

चित्र 10 में विभिन्न समाधानों के लिए समय के आंकड़ों का सारांश है।

चित्र 10:समाधानों का समय प्रदर्शन सारांश

तो इन सब से हमने क्या सीखा? मुझे लगता है कि इसे फिर से नहीं करना है! मजाक था। हमने सीखा है कि dbo.GetNumsAlanCharlieItzikBatch की तरह ऊर्ध्वाधर उन्मूलन अवधारणा का उपयोग करना सुरक्षित है, जो गैर-हेरफेर किए गए ROW_NUMBER परिणाम (rn) और हेरफेर किए गए (n) दोनों को उजागर करता है। बस यह सुनिश्चित करें कि जब आदेशित परिणाम वापस करने की आवश्यकता हो, तो हमेशा rn द्वारा आदेश दें, चाहे वह rn लौटा रहा हो या n।

यदि आप पूरी तरह से निश्चित हैं कि आपका समाधान हमेशा स्थिरांक के साथ इनपुट के रूप में उपयोग किया जाएगा, तो आप क्षैतिज इकाई उन्मूलन अवधारणा का उपयोग कर सकते हैं। यह उपयोगकर्ता के लिए एक अधिक सहज समाधान में परिणाम देगा, क्योंकि वे आरोही मूल्यों के लिए एक कॉलम के साथ बातचीत करेंगे। मैं अभी भी सुझाव देता हूं कि व्युत्पन्न तालिकाओं के साथ ट्रिक का उपयोग करने से बचें और फ़िल्टर ऑपरेटरों को शीर्ष ऑपरेटरों के ऊपर रखें यदि फ़ंक्शन को कभी भी गैर-निरंतर इनपुट के साथ उपयोग किया जाता है, तो बस सुरक्षित पक्ष पर रहने के लिए।

हम अभी भी नहीं कर रहे हैं। अगले महीने मैं अतिरिक्त समाधान तलाशना जारी रखूंगा।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. अनुमानों पर ध्यान देना

  2. शुरुआती के लिए SQL COALESCE फ़ंक्शन के साथ NULL मानों को प्रभावी ढंग से संभालना

  3. एसक्यूएल ट्यूटोरियल में शामिल होता है

  4. SQL INSERT क्वेरी में डुप्लीकेट रिकॉर्ड डालने से कैसे बचें (5 आसान तरीके)

  5. विस्तारित घटनाओं के साथ घटना हानि को समझना

© कॉपीराइट http://hi.sqldat.com सर्वाधिकार सुरक्षित