मेरे पास एक मेज पर एक निरंतर कम्प्यूटेड कॉलम है, जो केवल संक्षिप्त कॉलम से बना है, जैसे
CREATE TABLE dbo.T
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY,
A VARCHAR(20) NOT NULL,
B VARCHAR(20) NOT NULL,
C VARCHAR(20) NOT NULL,
D DATE NULL,
E VARCHAR(20) NULL,
Comp AS A + '-' + B + '-' + C PERSISTED NOT NULL
);
यह Comp
अद्वितीय नहीं है, और D प्रत्येक संयोजन की तिथि से मान्य है A, B, C
, इसलिए मैं प्रत्येक के लिए अंतिम तिथि A, B, C
(मूल रूप से Comp के समान मूल्य के लिए अगली आरंभ तिथि) प्राप्त करने के लिए निम्नलिखित क्वेरी का उपयोग करता हूं :
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1
WHERE t1.D IS NOT NULL -- DON'T CARE ABOUT INACTIVE RECORDS
ORDER BY t1.Comp;
फिर मैंने इस क्वेरी (और अन्य लोगों) में सहायता के लिए गणना किए गए कॉलम में एक इंडेक्स जोड़ा:
CREATE NONCLUSTERED INDEX IX_T_Comp_D ON dbo.T (Comp, D) WHERE D IS NOT NULL;
क्वेरी प्लान ने हालांकि मुझे चौंका दिया। मैंने सोचा होगा कि चूंकि मेरे पास एक क्लॉज है, जो कि D IS NOT NULL
मैं और मैं छांट रहे हैं Comp
, और सूचकांक के बाहर किसी भी कॉलम का उल्लेख नहीं कर रहे हैं कि गणना किए गए कॉलम पर सूचकांक को t1 और t2 स्कैन करने के लिए इस्तेमाल किया जा सकता है, लेकिन मैंने एक अनुक्रमणिका सूचकांक देखा स्कैन।
इसलिए मैंने इस सूचकांक के उपयोग को यह देखने के लिए मजबूर किया कि क्या यह एक बेहतर योजना है:
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1 WITH (INDEX (IX_T_Comp_D))
WHERE t1.D IS NOT NULL
ORDER BY t1.Comp;
जिससे यह योजना बनी
इससे पता चलता है कि कुंजी खोज का उपयोग किया जा रहा है, जिसके विवरण निम्नानुसार हैं:
अब SQL- सर्वर प्रलेखन के अनुसार:
आप एक गणना किए गए कॉलम पर एक इंडेक्स बना सकते हैं जिसे एक नियतात्मक, लेकिन अभेद्य, अभिव्यक्ति के साथ परिभाषित किया जाता है यदि कॉलम को क्रिएट टेबल या अन्य टेबल स्टेटमेंट में PERSISTED के रूप में चिह्नित किया गया है। इसका मतलब यह है कि डेटाबेस इंजन तालिका में गणना किए गए मानों को संग्रहीत करता है, और जब कोई अन्य कॉलम जिस पर गणना किए गए कॉलम को अद्यतन किया जाता है, तब उन्हें अपडेट करता है। डेटाबेस इंजन इन निरंतर मूल्यों का उपयोग करता है जब यह कॉलम पर एक इंडेक्स बनाता है, और जब किसी क्वेरी में इंडेक्स संदर्भित होता है। यह विकल्प आपको एक गणना किए गए कॉलम पर एक इंडेक्स बनाने में सक्षम बनाता है जब डेटाबेस इंजन सटीकता के साथ साबित नहीं कर सकता है कि क्या एक फ़ंक्शन जो कंप्यूटेड कॉलम एक्सप्रेशन देता है, विशेष रूप से एक CLR फ़ंक्शन जो .NET फ्रेमवर्क में बनाया गया है, दोनों नियतात्मक और सटीक है।
इसलिए, यदि डॉक्स का कहना है कि "डेटाबेस इंजन तालिका में गणना किए गए मानों को संग्रहीत करता है" , और मूल्य भी मेरे सूचकांक में संग्रहीत किया जा रहा है, तो एक कुंजी लुकअप को ए, बी और सी प्राप्त करने की आवश्यकता क्यों होती है जब उन्हें संदर्भित नहीं किया जाता है सब पर प्रश्न? मुझे लगता है कि वे COMP की गणना करने के लिए इस्तेमाल किया जा रहा है, लेकिन क्यों? इसके अलावा, क्वेरी इंडेक्स का उपयोग क्यों कर सकती है t2
, पर नहीं t1
?
एसक्यूएल फिडल पर क्वेरी और डीडीएल
NB मैंने SQL Server 2008 को टैग किया है क्योंकि यह वह संस्करण है जिस पर मेरी मुख्य समस्या है, लेकिन मुझे 2012 में भी यही व्यवहार मिला।