पिछले महीने, मैंने मांग के साथ आपूर्ति के मिलान की पीटर लार्सन की पहेली को कवर किया। मैंने पीटर का सीधा कर्सर-आधारित समाधान दिखाया और समझाया कि इसमें रैखिक स्केलिंग है। मैंने आपके लिए जो चुनौती छोड़ी है, वह है कार्य के लिए एक सेट-आधारित समाधान के साथ प्रयास करना और आना, और लड़के, क्या लोग चुनौती के लिए उठे हैं! आपके समाधान भेजने के लिए धन्यवाद लुका, कामिल कोस्नो, डैनियल ब्राउन, ब्रायन वॉकर, जो ओबिश, रेनर हॉफमैन, पॉल व्हाइट, चार्ली और निश्चित रूप से, पीटर लार्सन। कुछ विचार शानदार और एकमुश्त दिमाग उड़ाने वाले थे।
इस महीने, मैं सबमिट किए गए समाधानों की खोज शुरू करने जा रहा हूं, मोटे तौर पर, खराब प्रदर्शन से सबसे अच्छा प्रदर्शन करने वालों के लिए। खराब प्रदर्शन करने वालों से भी परेशान क्यों? क्योंकि आप अभी भी उनसे बहुत कुछ सीख सकते हैं; उदाहरण के लिए, विरोधी पैटर्न की पहचान करके। दरअसल, मेरे और पीटर सहित कई लोगों के लिए इस चुनौती को हल करने का पहला प्रयास अंतराल चौराहे की अवधारणा पर आधारित है। ऐसा होता है कि अंतराल चौराहे की पहचान के लिए क्लासिक विधेय-आधारित तकनीक का प्रदर्शन खराब है क्योंकि इसका समर्थन करने के लिए कोई अच्छी अनुक्रमण योजना नहीं है। यह लेख इस खराब प्रदर्शन करने वाले दृष्टिकोण को समर्पित है। खराब प्रदर्शन के बावजूद, समाधान पर काम करना एक दिलचस्प अभ्यास है। इसके लिए समस्या को इस तरह से मॉडलिंग करने के कौशल का अभ्यास करने की आवश्यकता है जो खुद को सेट-आधारित उपचार के लिए उधार दे। खराब प्रदर्शन के कारण की पहचान करना भी दिलचस्प है, जिससे भविष्य में विरोधी पैटर्न से बचना आसान हो जाता है। ध्यान रखें, यह समाधान केवल शुरुआती बिंदु है।
DDL और नमूना डेटा का एक छोटा सेट
एक अनुस्मारक के रूप में, कार्य में "नीलामी" नामक तालिका को क्वेरी करना शामिल है। तालिका बनाने के लिए निम्न कोड का उपयोग करें और नमूना डेटा के एक छोटे से सेट के साथ इसे पॉप्युलेट करें:
ड्रॉप टेबल अगर मौजूद है डीबीओ.नीलामी; क्रिएट टेबल डीबीओ.ऑक्शन (आईडी नॉट नॉट न्यूल आइडेंटिटी (1, 1) कॉन्स्ट्रेंट पीके_ऑक्शंस प्राइमरी की क्लस्टर, कोड चार्ज (1) नॉट न्यूल कॉन्स्ट्रेंट ck_Auctions_Code चेक (कोड ='डी' या कोड ='एस'), मात्रा डेसिमल (19) , 6) पूर्ण बाधा नहीं ck_Auctions_Quantity CHECK (मात्रा> 0)); खाता चालू करें; dbo.नीलामी से हटाएं; SET IDENTITY_INSERT dbo.नीलामी चालू; डीबीओ नीलामी (आईडी, कोड, मात्रा) मूल्यों (1, 'डी', 5.0), (2, 'डी', 3.0), (3, 'डी', 8.0), (5, 'डी') में डालें। 2.0), (6, 'डी', 8.0), (7, 'डी', 4.0), (8, 'डी', 2.0), (1000, 'एस', 8.0), (2000, 'एस', 6.0), (3000, 'एस', 2.0), (4000, 'एस', 2.0), (5000, 'एस', 4.0), (6000, 'एस', 3.0), (7000, 'एस', 2.0); SET IDENTITY_INSERT dbo.नीलामी बंद;
आपका काम ऐसे पेयरिंग बनाना था जो आपूर्ति से मेल खाने वाले आईडी ऑर्डरिंग के आधार पर मांग प्रविष्टियों के साथ एक अस्थायी तालिका में लिखते हैं। नमूना डेटा के छोटे सेट के लिए वांछित परिणाम निम्नलिखित है:
DemandID SupplyID TradeQuantity ----------- -------------------------------- 1 1000 5.0000002 1000 3.0000003 2000 6.0000003 3000 2.0000005 4000 2.0000006 5000 4.0000006 6000 3.0000006 7000 1.0000007 7000 1.000000
पिछले महीने, मैंने कोड भी प्रदान किया था जिसका उपयोग आप नीलामी तालिका को नमूना डेटा के एक बड़े सेट के साथ पॉप्युलेट करने के लिए कर सकते हैं, आपूर्ति और मांग प्रविष्टियों की संख्या के साथ-साथ उनकी मात्रा की सीमा को नियंत्रित कर सकते हैं। सुनिश्चित करें कि आप समाधानों के प्रदर्शन की जांच करने के लिए पिछले महीने के लेख के कोड का उपयोग करते हैं।
डेटा को अंतराल के रूप में मॉडलिंग करना
एक दिलचस्प विचार जो सेट-आधारित समाधानों का समर्थन करने के लिए उधार देता है, वह है डेटा को अंतराल के रूप में मॉडल करना। दूसरे शब्दों में, एक अंतराल के रूप में प्रत्येक मांग और आपूर्ति प्रविष्टि का प्रतिनिधित्व करते हैं, जो एक ही तरह (मांग या आपूर्ति) की कुल मात्रा के साथ शुरू होता है, लेकिन वर्तमान को छोड़कर, और वर्तमान सहित चल रहे कुल के साथ समाप्त होता है, निश्चित रूप से आईडी के आधार पर आदेश देना उदाहरण के लिए, नमूना डेटा के छोटे सेट को देखते हुए, पहली मांग प्रविष्टि (आईडी 1) 5.0 की मात्रा के लिए है और दूसरी (आईडी 2) 3.0 की मात्रा के लिए है। पहली मांग प्रविष्टि को अंतराल प्रारंभ के साथ दर्शाया जा सकता है:0.0, अंत:5.0, और दूसरी अंतराल प्रारंभ के साथ:5.0, अंत:8.0, और इसी तरह।
इसी तरह, पहली आपूर्ति प्रविष्टि (आईडी 1000) 8.0 की मात्रा के लिए है और दूसरा (ID 2000) 6.0 की मात्रा के लिए है। पहली आपूर्ति प्रविष्टि को अंतराल प्रारंभ के साथ दर्शाया जा सकता है:0.0, अंत:8.0, और दूसरा अंतराल प्रारंभ के साथ:8.0, अंत:14.0, और इसी तरह।
आपको जो मांग-आपूर्ति जोड़ी बनाने की आवश्यकता है, वे दो प्रकार के बीच प्रतिच्छेदन अंतराल के अतिव्यापी खंड हैं।
यह संभवतः डेटा के अंतराल-आधारित मॉडलिंग और वांछित परिणाम के दृश्य चित्रण के साथ सबसे अच्छी तरह से समझा जाता है, जैसा कि चित्र 1 में दिखाया गया है।
चित्र 1:अंतराल के रूप में डेटा की मॉडलिंग
चित्र 1 में दृश्य चित्रण बहुत ही आत्म-व्याख्यात्मक है, लेकिन संक्षेप में…
नीली आयतें अंतराल के रूप में मांग प्रविष्टियों का प्रतिनिधित्व करती हैं, अंतराल की शुरुआत के रूप में अनन्य चल रही कुल मात्रा और अंतराल के अंत के रूप में समावेशी चलने वाले कुल को दर्शाती हैं। पीले आयत आपूर्ति प्रविष्टियों के लिए समान करते हैं। फिर ध्यान दें कि दो प्रकार के प्रतिच्छेदन अंतरालों के अतिव्यापी खंड, जो हरे आयतों द्वारा दर्शाए गए हैं, मांग-आपूर्ति युग्म हैं जिन्हें आपको उत्पादित करने की आवश्यकता है। उदाहरण के लिए, पहला परिणाम युग्मन मांग आईडी 1, आपूर्ति आईडी 1000, मात्रा 5 के साथ है। दूसरा परिणाम जोड़ी मांग आईडी 2, आपूर्ति आईडी 1000, मात्रा 3 के साथ है। और इसी तरह।
सीटीई का उपयोग कर अंतराल चौराहों
इससे पहले कि आप अंतराल मॉडलिंग विचार के आधार पर समाधान के साथ टी-एसक्यूएल कोड लिखना शुरू करें, आपके पास पहले से ही एक सहज ज्ञान होना चाहिए कि यहां कौन से इंडेक्स उपयोगी हो सकते हैं। चूंकि आप चल रहे योगों की गणना के लिए विंडो फ़ंक्शंस का उपयोग करने की संभावना रखते हैं, इसलिए आप कॉलम कोड, आईडी और कॉलम मात्रा सहित एक कुंजी के साथ कवरिंग इंडेक्स से लाभ उठा सकते हैं। ऐसी अनुक्रमणिका बनाने के लिए यह कोड है:
अद्वितीय गैर-अनुक्रमित अनुक्रमणिका बनाएं idx_Code_ID_i_dbo पर मात्रा। नीलामी (कोड, आईडी) शामिल करें (मात्रा);
यह वही इंडेक्स है जिसकी मैंने पिछले महीने कर्सर-आधारित समाधान के लिए अनुशंसा की थी।
साथ ही, यहां बैच प्रोसेसिंग से लाभ होने की संभावना है। आप रोस्टोर पर बैच मोड की आवश्यकताओं के बिना इसके विचार को सक्षम कर सकते हैं, उदाहरण के लिए, SQL सर्वर 2019 एंटरप्राइज का उपयोग करके या बाद में, निम्नलिखित डमी कॉलमस्टोर इंडेक्स बनाकर:
dbo पर गैर-क्लस्टर किए गए कॉलमस्टोर इंडेक्स idx_cs बनाएं। नीलामी (आईडी) जहां आईडी =-1 और आईडी =-2;
अब आप समाधान के टी-एसक्यूएल कोड पर काम करना शुरू कर सकते हैं।
निम्नलिखित कोड मांग प्रविष्टियों का प्रतिनिधित्व करने वाले अंतराल बनाता है:
D0 AS के साथ-- D0 चल रही मांग की गणना EndDemand (चयन आईडी, मात्रा, SUM (मात्रा) के रूप में करता है (ID ROWS अनबाउंडेड PRECEDING द्वारा ऑर्डर) dbo से EndDemand के रूप में। नीलामी जहां कोड ='D'),-- D पिछले EndDemand को StartDemand के रूप में निकालता है, एक इंटरवलD AS के रूप में स्टार्ट-एंड की मांग को व्यक्त करता है (SELECT ID, मात्रा, EndDemand - मात्रा के रूप में StartDemand, EndDemand से D0) चुनें *D से;
CTE D0 फ़िल्टर को परिभाषित करने वाली क्वेरी नीलामी तालिका से प्रविष्टियों की मांग करती है और मांग अंतराल के अंतिम सीमांकक के रूप में चल रही कुल मात्रा की गणना करती है। फिर दूसरे CTE को परिभाषित करने वाली क्वेरी D, D0 को क्वेरी करती है और अंतिम सीमांकक से वर्तमान मात्रा घटाकर मांग अंतराल के प्रारंभ सीमांकक की गणना करती है।
यह कोड निम्न आउटपुट उत्पन्न करता है:
आईडी मात्रा स्टार्टडिमांड एंडडिमांड ---------------------------------------1 5.000000 0.000000 5.0000002 3.000000 5.000000 8.0000003 8.000000 8.000000 16.0000005 2.000000 16.000000 18.0000006 8.000000 18.000000 26.0000007 4.000000 26.000000 30.00008 2.000000 30.000000 32.000000
निम्न कोड का उपयोग करके आपूर्ति प्रविष्टियों के लिए समान तर्क लागू करके आपूर्ति अंतराल बहुत समान रूप से उत्पन्न होते हैं:
S0 AS के साथ-- S0 चल आपूर्ति की गणना EndSupply के रूप में करता है (ID, मात्रा, SUM (मात्रा) का चयन करें (ID ROWS अनबाउंडेड PRECEDING द्वारा ऑर्डर) dbo से EndSupply के रूप में। नीलामी जहां कोड ='S'),-- S एक्सट्रेक्ट्स पिछला एंडसप्ली को स्टार्टसप्लाई के रूप में, स्टार्ट-एंड सप्लाई को एक अंतराल के रूप में व्यक्त करते हुए एसएएस (चयन आईडी, मात्रा, एंडसप्लाई - मात्रा के रूप में स्टार्टसप्लाई, एंडसप्लाई से एस0) चुनें *एस से;
यह कोड निम्न आउटपुट उत्पन्न करता है:
आईडी मात्रा स्टार्टसप्लाई एंडसप्लाई-----------------------------------1000 8.000000 0.000000 8.0000002000 6.000000 8.000000 14.0000003000 2.000000 14.000000 16.0000004000 2.000000 16.000000 18.0000005000 4.000000 18.000000 22.0000006000 3.000000 22.000000 25.0000007000 2.000000 25.000000 27.000000
फिर जो बचा है वह है सीटीई डी और एस से प्रतिच्छेदन मांग और आपूर्ति अंतराल की पहचान करना, और उन प्रतिच्छेद अंतरालों के अतिव्यापी खंडों की गणना करना। याद रखें कि परिणाम युग्मों को एक अस्थायी तालिका में लिखा जाना चाहिए। यह निम्नलिखित कोड का उपयोग करके किया जा सकता है:
-- मौजूद होने पर टेम्परेरी टेबल ड्रॉप करेंड्रॉप टेबल अगर मौजूद है तो #MyPairings; D0 AS के साथ-- D0 चल रही मांग की गणना EndDemand के रूप में करता है StartDemand के रूप में, एक अंतराल के रूप में स्टार्ट-एंड की मांग को व्यक्त करनाD AS (चयन आईडी, मात्रा, एंडडिमांड - मात्रा के रूप में StartDemand, EndDemand FROM D0), S0 AS-- S0 चल आपूर्ति की गणना EndSupply (चयन आईडी, मात्रा, SUM (मात्रा) से अधिक के रूप में करता है। (आईडी पंक्तियों द्वारा ऑर्डर अनबाउंडेड प्रीसिडिंग) डीबीओ से एंडसप्लाई के रूप में। नीलामी जहां कोड ='एस'), - एस एक्सट्रैक्ट्स प्रीव एंडसप्ली को स्टार्ट सप्लाई के रूप में, स्टार्ट-एंड सप्लाई को अंतराल के रूप में व्यक्त करता है। StartSupply, EndSupply FROM S0)-- आउटर क्वेरी ट्रेडों को इंटरसेक्टिंग अंतरालों के ओवरलैपिंग सेगमेंट के रूप में पहचानती है-- इंटरसेक्टिंग डिमांड और सप्लाई इंटरवल्स में ट्रेड मात्रा तब होती है - LEAST(EndDemand, EndSupply) - GREATEST(StartDemsnad, StartSupply) सेलेक्ट करें डिमांड आईडी के रूप में डीआईडी, आपूर्ति आईडी के रूप में एसआईडी, मामला जो एन एंड डिमांड <एंड सप्लाई फिर एंड डिमांड ईएलएस एंड एंड सप्लाई एंड - केस जब स्टार्ट डिमांड> स्टार्ट सप्लाई फिर स्टार्ट डिमांड ELSE स्टार्ट सप्लाई खत्म ट्रेडक्वांटिटी के रूप में #MyPairingsFROM D INNER JOIN S ON D.StartDemandउस कोड के अलावा जो मांग और आपूर्ति अंतराल बनाता है, जिसे आप पहले ही देख चुके हैं, यहां मुख्य जोड़ बाहरी क्वेरी है, जो डी और एस के बीच प्रतिच्छेदन अंतराल की पहचान करता है, और अतिव्यापी खंडों की गणना करता है। इंटरसेक्टिंग अंतरालों की पहचान करने के लिए, बाहरी क्वेरी निम्नलिखित जॉइन विधेय का उपयोग करके D और S को जोड़ती है: D.StartDemandS.StartSupply अंतराल चौराहे की पहचान करने के लिए यह क्लासिक भविष्यवाणी है। यह समाधान के खराब प्रदर्शन का मुख्य स्रोत भी है, जैसा कि मैं जल्द ही समझाऊंगा।
बाहरी क्वेरी भी SELECT सूची में व्यापार मात्रा की गणना इस प्रकार करती है:
LEAST(EndDemand, EndSupply) - ग्रेटेस्ट (StartDemand, StartSupply)यदि आप Azure SQL का उपयोग कर रहे हैं, तो आप इस व्यंजक का उपयोग कर सकते हैं। यदि आप SQL Server 2019 या इससे पहले के संस्करण का उपयोग कर रहे हैं, तो आप निम्न तार्किक रूप से समकक्ष विकल्प का उपयोग कर सकते हैं:
मामला जब मांग समाप्त होता है <आपूर्ति समाप्त करें फिर मांग समाप्त करें अन्यथा आपूर्ति समाप्त करें - मामला जब मांग शुरू करें> आपूर्ति शुरू करें तब मांग शुरू करें अन्यथा आपूर्ति शुरू करें ENDचूंकि परिणाम को एक अस्थायी तालिका में लिखने की आवश्यकता थी, इसलिए बाहरी क्वेरी इसे प्राप्त करने के लिए SELECT INTO स्टेटमेंट का उपयोग करती है।
डेटा को अंतराल के रूप में मॉडल करने का विचार स्पष्ट रूप से पेचीदा और सुरुचिपूर्ण है। लेकिन प्रदर्शन के बारे में क्या? दुर्भाग्य से, इस विशिष्ट समाधान में एक बड़ी समस्या है कि कैसे अंतराल चौराहे की पहचान की जाती है। चित्र 2 में दिखाए गए इस समाधान की योजना की जांच करें।
चित्र 2:सीटीई समाधान का उपयोग कर चौराहों के लिए क्वेरी योजना
आइए योजना के सस्ते भागों के साथ शुरुआत करें।
नेस्टेड लूप्स जॉइन का बाहरी इनपुट मांग अंतराल की गणना करता है। यह मांग प्रविष्टियों को पुनः प्राप्त करने के लिए इंडेक्स सीक ऑपरेटर का उपयोग करता है, और बैच मोड विंडो एग्रीगेट ऑपरेटर का उपयोग मांग अंतराल अंत सीमांकक (इस योजना में एक्सप्र 1005 के रूप में संदर्भित) की गणना करने के लिए करता है। मांग अंतराल प्रारंभ सीमांकक तब Expr1005 - मात्रा (D से) है।
एक साइड नोट के रूप में, आपको बैच मोड विंडो एग्रीगेट ऑपरेटर से पहले एक स्पष्ट सॉर्ट ऑपरेटर का उपयोग आश्चर्यजनक रूप से मिल सकता है, क्योंकि इंडेक्स सीक से प्राप्त मांग प्रविष्टियां पहले से ही आईडी द्वारा ऑर्डर की जाती हैं जैसे विंडो फ़ंक्शन को उनकी आवश्यकता होती है। यह इस तथ्य से संबंधित है कि वर्तमान में, SQL सर्वर समानांतर बैच मोड विंडो एग्रीगेट ऑपरेटर से पहले समानांतर ऑर्डर-संरक्षण इंडेक्स ऑपरेशन के कुशल संयोजन का समर्थन नहीं करता है। यदि आप किसी सीरियल प्लान को केवल प्रयोग के उद्देश्य से लागू करते हैं, तो आप सॉर्ट ऑपरेटर को गायब होते हुए देखेंगे। SQL सर्वर ने समग्र रूप से निर्णय लिया, यहाँ समांतरता के उपयोग को प्राथमिकता दी गई, इसके परिणामस्वरूप अतिरिक्त स्पष्ट छँटाई हुई। लेकिन फिर से, योजना का यह हिस्सा चीजों की भव्य योजना में काम के एक छोटे से हिस्से का प्रतिनिधित्व करता है।
इसी तरह, नेस्टेड लूप्स का आंतरिक इनपुट आपूर्ति अंतराल की गणना करके शुरू होता है। उत्सुकता से, SQL सर्वर ने इस भाग को संभालने के लिए पंक्ति-मोड ऑपरेटरों का उपयोग करना चुना। एक तरफ, रनिंग टोटल की गणना करने के लिए उपयोग किए जाने वाले रो मोड ऑपरेटर्स में बैच मोड विंडो एग्रीगेट विकल्प की तुलना में अधिक ओवरहेड शामिल होता है; दूसरी ओर, SQL सर्वर के पास विंडो फ़ंक्शन की गणना के बाद ऑर्डर-संरक्षण इंडेक्स ऑपरेशन का एक कुशल समानांतर कार्यान्वयन है, इस भाग के लिए स्पष्ट सॉर्टिंग से परहेज करता है। यह उत्सुक है कि अनुकूलक ने मांग अंतराल के लिए एक रणनीति चुनी और दूसरी आपूर्ति अंतराल के लिए। किसी भी दर पर, इंडेक्स सीक ऑपरेटर आपूर्ति प्रविष्टियों को पुनः प्राप्त करता है, और कंप्यूट स्केलर ऑपरेटर तक ऑपरेटरों के बाद के अनुक्रम आपूर्ति अंतराल अंत सीमांकक की गणना करते हैं (इस योजना में एक्सप्र 1009 के रूप में संदर्भित)। आपूर्ति अंतराल प्रारंभ सीमांकक तब Expr1009 - मात्रा (S से) है।
इन दो भागों का वर्णन करने के लिए मैंने जितने पाठ का उपयोग किया है, योजना में काम का वास्तव में महंगा हिस्सा वह है जो आगे आता है।
अगले भाग को निम्नलिखित विधेय का उपयोग करके मांग अंतराल और आपूर्ति अंतराल में शामिल होने की आवश्यकता है:
D.StartDemandS.StartSupply डीआई मांग अंतराल और एसआई आपूर्ति अंतराल को मानते हुए, कोई सहायक सूचकांक नहीं होने के कारण, इसमें डीआई * एसआई पंक्तियों को संसाधित करना शामिल होगा। चित्रा 2 में योजना नीलामी तालिका को 400,000 पंक्तियों (200,000 मांग प्रविष्टियों और 200,000 आपूर्ति प्रविष्टियों) के साथ भरने के बाद बनाई गई थी। इसलिए, बिना किसी सहायक सूचकांक के, योजना को 200,000 * 200,000 =40,000,000,000 पंक्तियों को संसाधित करने की आवश्यकता होगी। इस लागत को कम करने के लिए, अनुकूलक ने कुंजी के रूप में आपूर्ति अंतराल अंत सीमांकक (Expr1009) के साथ एक अस्थायी सूचकांक (सूचकांक स्पूल ऑपरेटर देखें) बनाना चुना। यह काफी अच्छा है जो यह कर सकता है। हालाँकि, यह समस्या के केवल एक हिस्से का ख्याल रखता है। दो रेंज विधेय के साथ, केवल एक को एक इंडेक्स द्वारा समर्थित किया जा सकता है जो विधेय की तलाश करता है। दूसरे को अवशिष्ट विधेय का उपयोग करके संभाला जाना है। वास्तव में, आप योजना में देख सकते हैं कि अस्थायी अनुक्रमणिका में खोज, खोज विधेय Expr1009> Expr1005 – D.Quantity का उपयोग करती है, इसके बाद फ़िल्टर ऑपरेटर अवशिष्ट विधेय Expr1005> Expr1009 – S.Quantity को संभालता है।
औसतन मान लें, सीक विधेय सूचकांक प्रति मांग पंक्ति से आधी आपूर्ति पंक्तियों को अलग करता है, इंडेक्स स्पूल ऑपरेटर से उत्सर्जित और फ़िल्टर ऑपरेटर द्वारा संसाधित पंक्तियों की कुल संख्या तब DI * SI / 2 है। हमारे मामले में, 200,000 के साथ मांग पंक्तियाँ और 200,000 आपूर्ति पंक्तियाँ, यह 20,000,000,000 में तब्दील हो जाती है। दरअसल, इंडेक्स स्पूल ऑपरेटर से फ़िल्टर ऑपरेटर तक जाने वाला एरो इसके करीब कई पंक्तियों की रिपोर्ट करता है।
पिछले महीने से कर्सर-आधारित समाधान के रैखिक स्केलिंग की तुलना में इस योजना में द्विघात स्केलिंग है। आप चित्र 3 में दो समाधानों की तुलना करते हुए एक प्रदर्शन परीक्षण का परिणाम देख सकते हैं। आप सेट-आधारित समाधान के लिए अच्छी तरह से आकार के परवलय को स्पष्ट रूप से देख सकते हैं।
चित्र 3:CTEs समाधान बनाम कर्सर-आधारित समाधान का उपयोग करके चौराहों का प्रदर्शन
अस्थायी तालिकाओं का उपयोग कर अंतराल चौराहों
आप अस्थायी तालिकाओं के साथ मांग और आपूर्ति अंतराल के लिए सीटीई के उपयोग को बदलकर और इंडेक्स स्पूल से बचने के लिए चीजों को कुछ हद तक सुधार सकते हैं, आपूर्ति अंतराल को कुंजी के रूप में अंतिम सीमांकक के साथ अस्थायी तालिका पर अपना खुद का इंडेक्स बना सकते हैं। यहाँ संपूर्ण समाधान का कोड है:
-- मौजूद होने पर अस्थायी टेबल ड्रॉप करेंड्रॉप टेबल अगर मौजूद है तो #MyPairings, #Demand, #Supply; D0 AS के साथ-- D0 चल रही मांग की गणना EndDemand के रूप में करता है StartDemand के रूप में, एक अंतराल के रूप में स्टार्ट-एंड की मांग को व्यक्त करनाD AS (चयन आईडी, मात्रा, एंडडिमांड - मात्रा के रूप में StartDemand, EndDemand FROM D0) चयन आईडी, मात्रा, CAST(ISNULL(StartDemand, 0.0) AS DECIMAL(19, 6)) AS StartDemand, CAST(ISNULL(EndDemand, 0.0) AS DECIMAL(19, 6)) EndDemandINTO #DemandFROM D के रूप में; S0 AS के साथ-- S0 चल आपूर्ति की गणना EndSupply (चयन आईडी, मात्रा, योग (मात्रा) से अधिक (आईडी द्वारा आदेश) के रूप में करता है पंक्तियाँ असीमित पूर्ववर्ती) डीबीओ से एंडसप्लाई के रूप में। नीलामी जहां कोड ='एस'), - एस एक्सट्रेक्ट्स प्रीव एंडसप्ली को स्टार्टसप्लाई के रूप में, स्टार्ट-एंड सप्लाई को अंतराल के रूप में व्यक्त करता है। S0) चयन आईडी, मात्रा, कास्ट (ISNULL(StartSupply, 0.0) दशमलव के रूप में(19, 6)) StartSupply के रूप में, CAST(ISNULL(EndSupply, 0.0) दशमलव के रूप में(19, 6)) EndSupplyINTO #SupplyFROM S के रूप में; #Supply(EndSupply, ID) पर UNIQUE CLUSTERED INDEX idx_cl_ES_ID बनाएं; - बाहरी क्वेरी इंटरसेक्टिंग अंतराल के ओवरलैपिंग सेगमेंट के रूप में ट्रेडों की पहचान करती है-- इंटरसेक्टिंग मांग और आपूर्ति अंतराल में व्यापार मात्रा तब होती है - LEAST(EndDemand, EndSupply) - GREATEST (StartDemsnad, StartSupply) D.ID AS डिमांड आईडी चुनें, आपूर्ति आईडी के रूप में एसआईडी, मामला जब मांग समाप्त होता है <समाप्त आपूर्ति तब समाप्त होती है और आपूर्ति समाप्त होती है - मामला जब प्रारंभ मांग> प्रारंभ आपूर्ति फिर प्रारंभ मांग और ईएलएसई प्रारंभ आपूर्ति समाप्त ट्रेडक्वांटिटी के रूप में #MyPairings#मांग के रूप में डी आंतरिक के रूप में डी। S.EndSupply और D.EndDemand> S.StartSupply;इस समाधान की योजनाएँ चित्र 4 में दिखाई गई हैं:
चित्र 4:अस्थायी तालिका समाधान का उपयोग कर चौराहों के लिए क्वेरी योजना
पहली दो योजनाएं आपूर्ति और मांग अंतराल की गणना करने के लिए बैच-मोड इंडेक्स सीक + सॉर्ट + विंडो एग्रीगेट ऑपरेटरों के संयोजन का उपयोग करती हैं और उन्हें अस्थायी तालिकाओं में लिखती हैं। तीसरी योजना #Supply तालिका पर अनुक्रमणिका निर्माण को EndSupply सीमांकक के साथ प्रमुख कुंजी के रूप में संभालती है।
चौथी योजना काम के बड़े हिस्से का प्रतिनिधित्व करती है, जिसमें नेस्टेड लूप्स जॉइन ऑपरेटर होता है जो #Demand से प्रत्येक अंतराल से मेल खाता है, #सप्लाई से इंटरसेक्टिंग अंतराल। यह भी देखें कि यहां भी, इंडेक्स सीक ऑपरेटर विधेय पर निर्भर करता है #Supply.EndSupply> #Demand.StartDemand खोज विधेय के रूप में, और #Demand.EndDemand> #Supply.StartSupply अवशिष्ट विधेय के रूप में। तो जटिलता/स्केलिंग के संदर्भ में, आपको पिछले समाधान की तरह ही द्विघात जटिलता मिलती है। आप केवल प्रति पंक्ति कम भुगतान करते हैं क्योंकि आप पिछली योजना द्वारा उपयोग किए गए इंडेक्स स्पूल के बजाय अपने स्वयं के इंडेक्स का उपयोग कर रहे हैं। आप चित्र 5 में पिछले दो की तुलना में इस समाधान का प्रदर्शन देख सकते हैं।
चित्र 5:अन्य दो समाधानों की तुलना में अस्थायी तालिकाओं का उपयोग करके चौराहों का प्रदर्शन
जैसा कि आप देख सकते हैं, अस्थायी तालिकाओं के साथ समाधान सीटीई के साथ बेहतर प्रदर्शन करता है, लेकिन इसमें अभी भी द्विघात स्केलिंग है और कर्सर की तुलना में बहुत खराब है।
आगे क्या है?
इस आलेख में सेट-आधारित समाधान का उपयोग करके मांग कार्य के साथ क्लासिक मिलान आपूर्ति को संभालने के पहले प्रयास को कवर किया गया था। यह विचार था कि डेटा को अंतराल के रूप में मॉडल किया जाए, आपूर्ति और मांग अंतरालों की पहचान करके मांग प्रविष्टियों के साथ आपूर्ति का मिलान किया जाए, और फिर अतिव्यापी खंडों के आकार के आधार पर व्यापारिक मात्रा की गणना की जाए। निश्चित रूप से एक दिलचस्प विचार। इसके साथ मुख्य समस्या दो रेंज विधेय का उपयोग करके अंतराल चौराहे की पहचान करने की क्लासिक समस्या भी है। यहां तक कि सबसे अच्छे इंडेक्स के साथ, आप इंडेक्स की तलाश के साथ केवल एक रेंज विधेय का समर्थन कर सकते हैं; अन्य श्रेणी विधेय को अवशिष्ट विधेय का उपयोग करके नियंत्रित किया जाना है। इसका परिणाम द्विघात जटिलता वाली योजना में होता है।
तो इस बाधा को दूर करने के लिए आप क्या कर सकते हैं? कई अलग-अलग विचार हैं। एक शानदार विचार जो ओबिश का है, जिसके बारे में आप उनके ब्लॉग पोस्ट में विस्तार से पढ़ सकते हैं। मैं श्रृंखला में आने वाले लेखों में अन्य विचारों को शामिल करूंगा।
[ यहां जाएं:मूल चुनौती | समाधान:भाग 1 | भाग 2 | भाग 3 ]