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

ओवरलैपिंग प्रश्नों का अनुकूलन भाग 1:परिचय और उन्नत टी-एसक्यूएल समाधान

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

अस्थायी डेटा का परिचय

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

टेम्पोरल टेबल के प्रकार

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

दूसरा अस्थायी मुद्दा है लेन-देन का समय . ऊपर वर्णित अनुबंध के लिए एक पंक्ति समय बिंदु 1 पर डाली गई थी और डेटाबेस के लिए ज्ञात सत्य का एकमात्र संस्करण था जब तक कि किसी ने इसे बदल नहीं दिया, या यहां तक ​​​​कि समय के अंत तक। जब पंक्ति को समय बिंदु 2 पर अद्यतन किया जाता है, तो मूल पंक्ति को समय बिंदु 1 से समय बिंदु 2 तक डेटाबेस के लिए सही होने के रूप में जाना जाता था। उसी प्रस्ताव के लिए एक नई पंक्ति समय बिंदु 2 से डेटाबेस के लिए मान्य समय के साथ डाली जाती है। समय का अंत। लेन-देन के समय को सिस्टम समय . के रूप में भी जाना जाता है या डेटाबेस समय

बेशक, आप एप्लिकेशन और सिस्टम वर्जन टेबल दोनों को भी लागू कर सकते हैं। ऐसी तालिकाओं को बिटेम्पोरल . कहा जाता है टेबल।

SQL सर्वर 2016 में, आपको सिस्टम वर्जन्ड टेम्पोरल टेबल के साथ सिस्टम टाइम आउट ऑफ बॉक्स के लिए सपोर्ट मिलता है। . यदि आपको आवेदन समय को लागू करने की आवश्यकता है, तो आपको स्वयं एक समाधान विकसित करने की आवश्यकता है।

एलन इंटरवल ऑपरेटर्स

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

मैं पहले उस संकेतन का परिचय देता हूं जिसका मैं उपयोग करूंगा। मैं दो अंतरालों पर काम करूंगा, जिन्हें i1 . के रूप में दर्शाया गया है और i2 . पहले अंतराल का आरंभिक समय बिंदु b1 . है , और अंत है e1 ; दूसरे अंतराल का आरंभिक समय बिंदु b2 . है और अंत है e2 . एलन के बूलियन ऑपरेटर निम्न तालिका में परिभाषित किया गया है।

[तालिका id=2 /]
बूलियन ऑपरेटरों के अलावा, एलन के तीन ऑपरेटर हैं जो अंतराल को इनपुट पैरामीटर के रूप में स्वीकार करते हैं और एक अंतराल लौटाते हैं। ये ऑपरेटर सरल अंतराल बीजगणित बनाते हैं . ध्यान दें कि उन ऑपरेटरों का नाम रिलेशनल ऑपरेटरों के समान है, जिनसे आप शायद पहले से ही परिचित हैं:यूनियन, इंटरसेक्ट और माइनस। हालाँकि, वे बिल्कुल अपने संबंधपरक समकक्षों की तरह व्यवहार नहीं करते हैं। सामान्य तौर पर, तीन अंतराल ऑपरेटरों में से किसी का उपयोग करते हुए, यदि ऑपरेशन के परिणामस्वरूप समय बिंदुओं का एक खाली सेट होता है या एक सेट में जिसे एक अंतराल द्वारा वर्णित नहीं किया जा सकता है, तो ऑपरेटर को NULL वापस करना चाहिए। दो अंतरालों का मिलन तभी समझ में आता है जब अंतराल मिलते हैं या ओवरलैप होते हैं। एक चौराहा तभी समझ में आता है जब अंतराल ओवरलैप हो। माइनस इंटरवल ऑपरेटर कुछ मामलों में ही समझ में आता है। उदाहरण के लिए, (3:10) माइनस (5:7) NULL लौटाता है क्योंकि परिणाम को एक अंतराल द्वारा वर्णित नहीं किया जा सकता है। निम्न तालिका अंतराल बीजगणित के संचालकों की परिभाषा को सारांशित करती है।

[टेबल आईडी=3 /]

ओवरलैपिंग क्वेरी प्रदर्शन समस्या ओवरलैप लागू करने के लिए सबसे जटिल ऑपरेटरों में से एक है ऑपरेटर। जिन प्रश्नों को ओवरलैपिंग अंतराल खोजने की आवश्यकता होती है, उन्हें अनुकूलित करना आसान नहीं होता है। हालाँकि, इस तरह के प्रश्न टेम्पोरल टेबल पर काफी बार होते हैं। इस और अगले दो लेखों में, मैं आपको ऐसे प्रश्नों को अनुकूलित करने के कुछ तरीके दिखाऊंगा। लेकिन इससे पहले कि मैं समाधान पेश करूं, मुझे समस्या का परिचय दें।

समस्या की व्याख्या करने के लिए, मुझे कुछ डेटा चाहिए। निम्न कोड एक उदाहरण दिखाता है कि b . के साथ व्यक्त वैधता अंतराल के साथ तालिका कैसे बनाई जाए और कॉलम, जहां एक अंतराल की शुरुआत और अंत को पूर्णांक के रूप में दर्शाया जाता है। तालिका WideWorldImporters.Sales.OrderLines तालिका के डेमो डेटा से भरी हुई है। कृपया ध्यान दें कि WideWorldImporters . के कई संस्करण हैं डेटाबेस, इसलिए आपको थोड़ा अलग परिणाम मिल सकते हैं। मैंने अपने SQL सर्वर इंस्टेंस पर इस डेमो डेटाबेस को पुनर्स्थापित करने के लिए https://github.com/Microsoft/sql-server-samples/releases/tag/wide-world-importers-v1.0 से WideWorldImporters-Standard.bak बैकअप फ़ाइल का उपयोग किया ।

डेमो डेटा बनाना

मैंने एक डेमो टेबल बनाया है dbo.Intervals tempd . में निम्नलिखित कोड के साथ डेटाबेस।

USE tempdb;
GO

SELECT OrderLineID AS id,
 StockItemID * (OrderLineID % 5 + 1) AS b,
 LastEditedBy + StockItemID * (OrderLineID % 5 + 1) AS e
INTO dbo.Intervals
FROM WideWorldImporters.Sales.OrderLines;
-- 231412 rows
GO

ALTER TABLE dbo.Intervals ADD CONSTRAINT PK_Intervals PRIMARY KEY(id);
CREATE INDEX idx_b ON dbo.Intervals(b) INCLUDE(e);
CREATE INDEX idx_e ON dbo.Intervals(e) INCLUDE(b);
GO

कृपया अनुक्रमणिका पर भी ध्यान दें बनाया था। अंतराल की शुरुआत या अंतराल के अंत में खोजों के लिए दो अनुक्रमणिका इष्टतम हैं। आप निम्न कोड के साथ सभी अंतरालों के न्यूनतम प्रारंभ और अधिकतम अंत की जांच कर सकते हैं।

SELECT MIN(b), MAX(e)
FROM dbo.Intervals;

आप परिणामों में देख सकते हैं कि न्यूनतम प्रारंभ समय बिंदु 1 है और अधिकतम समाप्ति समय बिंदु 1155 है।

डेटा को संदर्भ देना

आप देख सकते हैं कि मैं शुरुआत और अंत का प्रतिनिधित्व करता हूं समय बिंदु पूर्णांकों के रूप में। अब मुझे अंतराल को कुछ समय संदर्भ देने की जरूरत है। इस मामले में, एक एकल समय बिंदु दिन . का प्रतिनिधित्व करता है . निम्न कोड एक तारीख लुकअप तालिका बनाता है और आबाद करता है। ध्यान दें कि आरंभ होने की तारीख 1 जुलाई 2014 है।

CREATE TABLE dbo.DateNums
 (n INT NOT NULL PRIMARY KEY,
  d DATE NOT NULL);
GO

DECLARE @i AS INT = 1, 
 @d AS DATE = '20140701';
WHILE @i <= 1200
BEGIN
INSERT INTO dbo.DateNums
 (n, d)
SELECT @i, @d;
SET @i += 1;
SET @d = DATEADD(day,1,@d);
END;
GO

अब, आप dbo.Intervals तालिका को dbo.DateNums तालिका में दो बार शामिल कर सकते हैं, ताकि उन पूर्णांकों को संदर्भ दिया जा सके जो अंतरालों की शुरुआत और अंत का प्रतिनिधित्व करते हैं।

SELECT i.id,
 i.b, d1.d AS dateB,
 i.e, d2.d AS dateE
FROM dbo.Intervals AS i
 INNER JOIN dbo.DateNums AS d1
  ON i.b = d1.n
 INNER JOIN dbo.DateNums AS d2
  ON i.e = d2.n
ORDER BY i.id;

प्रदर्शन समस्या का परिचय

अस्थायी प्रश्नों के साथ समस्या यह है कि तालिका से पढ़ते समय, SQL सर्वर केवल एक अनुक्रमणिका का उपयोग कर सकता है, और उन पंक्तियों को सफलतापूर्वक समाप्त कर सकता है जो केवल एक तरफ से परिणाम के लिए उम्मीदवार नहीं हैं, और फिर शेष डेटा को स्कैन करते हैं। उदाहरण के लिए, आपको तालिका में सभी अंतरालों को खोजने की आवश्यकता है जो किसी दिए गए अंतराल के साथ ओवरलैप करते हैं। याद रखें, दो अंतराल तब ओवरलैप होते हैं जब पहली की शुरुआत दूसरे के अंत के बराबर या कम होती है और दूसरे की शुरुआत पहले वाले के अंत से कम या बराबर होती है, या गणितीय रूप से जब (b1 ≤ e2) और (b2 e1)।

निम्न क्वेरी ने अंतराल (10, 30) के साथ ओवरलैप होने वाले सभी अंतरालों की खोज की। ध्यान दें कि दूसरी शर्त (b2 e1) को आसान पढ़ने के लिए (e1 ≥ b2) में बदल दिया जाता है (तालिका से अंतराल की शुरुआत और अंत हमेशा स्थिति के बाईं ओर होते हैं)। दिया गया, या खोजा गया अंतराल, तालिका में सभी अंतरालों के लिए समयरेखा की शुरुआत में है।

SET STATISTICS IO ON;
DECLARE @b AS INT = 10,
 @e AS INT = 30;
SELECT id, b, e
FROM dbo.Intervals
WHERE b <= @e
  AND e >= @b
OPTION (RECOMPILE);

क्वेरी ने 36 तार्किक रीड्स का इस्तेमाल किया। यदि आप निष्पादन योजना की जांच करते हैं, तो आप देख सकते हैं कि क्वेरी ने idx_b इंडेक्स में सीक विधेय [tempdb] के साथ इंडेक्स सीक का उपयोग किया है। [dbo]। [अंतराल]। b <=स्केलर ऑपरेटर ((30)) और फिर स्कैन करें पंक्तियों और अवशिष्ट विधेय [tempdb] का उपयोग करके परिणामी पंक्तियों का चयन करें। [dbo]। [अंतराल]। [e]> =(10)। क्योंकि खोजा गया अंतराल समयरेखा की शुरुआत में है, इसलिए खोज विधेय ने अधिकांश पंक्तियों को सफलतापूर्वक समाप्त कर दिया; तालिका में केवल कुछ अंतरालों का आरंभिक बिंदु 30 से कम या उसके बराबर होता है।

यदि खोजा गया अंतराल समयरेखा के अंत में होगा, तो आपको समान रूप से कुशल क्वेरी मिलेगी, बस SQL ​​सर्वर idx_e अनुक्रमणिका का उपयोग करने के लिए उपयोग करेगा। हालांकि, क्या होता है यदि खोजा गया अंतराल टाइमलाइन के बीच में होता है, जैसा कि निम्न क्वेरी दिखाती है?

DECLARE @b AS INT = 570,
 @e AS INT = 590;
SELECT id, b, e
FROM dbo.Intervals
WHERE b <= @e
  AND e >= @b
OPTION (RECOMPILE);

इस बार, क्वेरी ने 111 तार्किक रीड्स का उपयोग किया। बड़ी तालिका के साथ, पहली क्वेरी के साथ अंतर और भी बड़ा होगा। यदि आप निष्पादन योजना की जांच करते हैं, तो आप यह पता लगा सकते हैं कि SQL सर्वर ने [tempdb] के साथ idx_e अनुक्रमणिका का उपयोग किया है। डीबीओ]। [अंतराल]। [बी] <=(590) अवशिष्ट विधेय। खोज विधेय एक तरफ से लगभग आधी पंक्तियों को बाहर करता है, जबकि दूसरी तरफ से आधी पंक्तियों को स्कैन किया जाता है और परिणामी पंक्तियों को अवशिष्ट विधेय के साथ निकाला जाता है।

उन्नत T-SQL समाधान

एक समाधान है जो उस अनुक्रमणिका का उपयोग एकल अनुक्रमणिका का उपयोग करके खोजे गए अंतराल के दोनों ओर से पंक्तियों को समाप्त करने के लिए करेगा। निम्न आंकड़ा इस तर्क को दर्शाता है।

आकृति में अंतराल को निचली सीमा द्वारा क्रमबद्ध किया जाता है, जो SQL सर्वर के idx_b अनुक्रमणिका के उपयोग का प्रतिनिधित्व करता है। दिए गए (खोजे गए) अंतराल के दाईं ओर से अंतराल को हटाना सरल है:केवल उन सभी अंतरालों को समाप्त करें जहां शुरुआत दिए गए अंतराल के अंत की कम से कम एक इकाई बड़ी (दाईं ओर अधिक) हो। आप इस सीमा को सबसे दाईं बिंदीदार रेखा से दर्शाए गए चित्र में देख सकते हैं। हालाँकि, बाईं ओर से हटाना अधिक जटिल है। समान अनुक्रमणिका का उपयोग करने के लिए, बाईं ओर से समाप्त करने के लिए idx_b अनुक्रमणिका, मुझे क्वेरी के WHERE खंड में तालिका में अंतराल की शुरुआत का उपयोग करने की आवश्यकता है। मुझे दिए गए (खोजे गए) अंतराल की शुरुआत से कम से कम तालिका में सबसे लंबे अंतराल की लंबाई के लिए बाईं ओर जाना है, जो कि आकृति में कॉलआउट के साथ चिह्नित है। बाईं पीली रेखा से पहले शुरू होने वाले अंतराल दिए गए (नीले) अंतराल के साथ ओवरलैप नहीं हो सकते।

चूंकि मुझे पहले से ही पता है कि सबसे लंबे अंतराल की लंबाई 20 है, मैं एक बेहतर क्वेरी को काफी सरल तरीके से लिख सकता हूं।

DECLARE @b AS INT = 570,
 @e AS INT = 590;
DECLARE @max AS INT = 20;
SELECT id, b, e
FROM dbo.Intervals
WHERE b <= @e AND b >= @b - @max
  AND e >= @b AND e <= @e + @max
OPTION (RECOMPILE);

यह क्वेरी पिछली पंक्तियों की तरह ही 20 लॉजिकल रीड के साथ समान पंक्तियों को पुनः प्राप्त करती है। यदि आप निष्पादन योजना की जाँच करते हैं, तो आप देख सकते हैं कि idx_b का उपयोग किया गया था, सीक विधेय सीक कीज़ के साथ [1]:प्रारंभ:[tempdb]। [dbo]। [अंतराल]। b>=स्केलर ऑपरेटर ((550)) , अंत:[tempdb]। [अंतराल]।[e]>=(570) और [tempdb]।[dbo]। [अंतराल]।[e]<=(610) का उपयोग बहुत सीमित आंशिक स्कैन से पंक्तियों का चयन करने के लिए किया गया था।

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

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

निष्कर्ष

कृपया ध्यान दें कि यह सिर्फ एक संभावित समाधान है। आप एक समाधान ढूंढ सकते हैं जो अधिक जटिल है, फिर भी यह अनुमानित प्रदर्शन देता है, चाहे इट्ज़िक बेन-गण (http://sqlmag.com/t-sql/) द्वारा SQL सर्वर आलेख में अंतराल क्वेरीज़ में सबसे लंबे अंतराल की लंबाई की परवाह किए बिना। एसक्यूएल-सर्वर-अंतराल-प्रश्न)। हालांकि, मुझे वास्तव में उन्नत T-SQL पसंद है समाधान मैंने इस लेख में प्रस्तुत किया है। समाधान बहुत आसान है; आपको केवल अपने अतिव्यापी प्रश्नों के WHERE खंड में दो विधेय जोड़ने की आवश्यकता है। हालांकि, यह संभावनाओं का अंत नहीं है। बने रहें, अगले दो लेखों में मैं आपको और समाधान दिखाऊंगा, जिससे आपके पास अपने अनुकूलन टूलबॉक्स में संभावनाओं का एक समृद्ध समूह होगा।

उपयोगी टूल:

SQL सर्वर के लिए dbForge क्वेरी बिल्डर - उपयोगकर्ताओं को मैन्युअल कोड लेखन के बिना सहज ज्ञान युक्त दृश्य इंटरफ़ेस के माध्यम से त्वरित और आसानी से जटिल SQL क्वेरी बनाने की अनुमति देता है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL में किसी संख्या को निकटतम पूर्णांक तक कैसे पूर्णांकित करें?

  2. कुंडी का परिचय

  3. जूमला के टेम्प्लेट के लिए शीर्ष 9 डेटाबेस प्रबंधन प्रणाली

  4. समानांतर योजनाएँ कैसे शुरू होती हैं - भाग 2

  5. ट्रेस फ्लैग 2389 और नया कार्डिनैलिटी अनुमानक