कम्प्यूटेड कॉलम इंडेक्स का उपयोग नहीं किया गया


14

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

ऐसा लगता है कि इस तरह के कुछ अन्य प्रश्न हैं, लेकिन कोई भी इस बात पर ध्यान केंद्रित नहीं करता है कि सूचकांक का उपयोग क्यों नहीं किया जाएगा।

टेस्ट टेबल:

CREATE TABLE dbo.Diffs
    (
    Id int NOT NULL IDENTITY (1, 1),
    DataA int NULL,
    DataB int NULL,
    DiffPersisted  AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0) PERSISTED ,
    DiffComp  AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0),
    DiffStatic bit not null,
    Primary Key (Id)
    )

create index ix_DiffPersisted on Diffs (DiffPersisted)
create index ix_DiffComp on Diffs (DiffComp)
create index ix_DiffStatic on Diffs (DiffStatic)

और प्रश्न:

select Id from Diffs where DiffPersisted = 1
select Id from Diffs where DiffComp = 1
select Id from Diffs where DiffStatic = 1

और परिणामस्वरूप निष्पादन योजनाएं: निष्पादन योजना

जवाबों:


10

के COALESCEबजाय के साथ की कोशिश करो ISNULL। साथ ISNULL, एसक्यूएल सर्वर संकरा सूचकांक के खिलाफ एक विधेय धक्का करने में सक्षम प्रतीत नहीं होता है, और इसलिए जानकारी प्राप्त करने के क्लस्टर स्कैन करने के लिए है।

CREATE TABLE dbo.Diffs
    (
    Id int NOT NULL IDENTITY (1, 1),
    DataA int NULL,
    DataB int NULL,
    DiffPersisted  AS COALESCE(convert(bit, case when [DataA] is null 
      and [DataB] is not null then 1 when [DataA] <> [DataB] 
      then 1 else 0 end), 0) PERSISTED ,
    DiffComp  AS COALESCE(convert(bit, case when [DataA] is null 
      and [DataB] is not null then 1 when [DataA] <> [DataB] 
      then 1 else 0 end), 0),
    DiffStatic bit not null,
    Primary Key (Id)
    );

कहा कि, यदि आप एक स्थिर स्तंभ के साथ चिपके रहते हैं, तो एक फ़िल्टर किया गया इंडेक्स अधिक अर्थ लगा सकता है, और इसमें I / O लागत कम होगी (यह सब इस बात पर निर्भर करता है कि आम तौर पर फ़िल्टर पंक्तियों से कितनी पंक्तियाँ मेल खाती हैं) जैसे:

CREATE INDEX ix_DiffStaticFiltered 
  ON dbo.Diffs(DiffStatic)
  WHERE DiffStatic = 1;

बहुत दिलचस्प है, यह नहीं सोचा होगा। ऐसा लगता है जैसे आप सिर्फ COALESCEइस बिंदु पर छुटकारा पा सकते हैं ; मेरा मानना ​​है कि CASEविवरण पहले से ही वापस करने की गारंटी थी 0या 1, लेकिन ISNULLकेवल मौजूद एसक्यूएल सर्वर BITही गणना किए गए कॉलम के लिए गैर-अशक्त होगा । हालांकि, COALESCEअभी भी एक अशक्त स्तंभ निकलेगा। इस परिवर्तन का एक प्रभाव, इसके साथ या उसके बिना COALESCE, यह है कि गणना किया गया स्तंभ अब अशक्त है, लेकिन सूचकांक की तलाश की जा सकती है।
ज्योफ पैटरसन

@Geoff हाँ, यह सच है। लेकिन इस मामले में चूंकि हम गणना किए गए कॉलम की परिभाषा से जानते हैं कि NULL वास्तव में एक संभावित आउटपुट नहीं है, यह वास्तव में केवल तभी मायने रखता है जब हम इस तालिका को SELECT INTO के स्रोत के रूप में उपयोग कर रहे हैं।
हारून बर्ट्रेंड

यह कुछ आश्चर्यजनक जानकारी है - धन्यवाद! मेरा अंतिम लक्ष्य यह है कि DataA और DataB कॉलम का उपयोग "गंदे" uuids के रूप में किया जाता है ताकि रिकॉर्ड पर असंबद्ध कॉलम के अतुल्यकालिक अद्यतन के लिए अनुमति दी जा सके, इसलिए बहुत सारे ऐसे स्थान नहीं होने चाहिए जहाँ पर Diff ध्वज 1. यदि मैं स्थैतिक का उपयोग करता हूँ क्षेत्र, तब मैं दो uuids पर नजर रखने और क्षेत्र को अद्यतन करने के लिए एक ट्रिगर जोड़ने के बारे में सोच रहा था।
डेविड फेइवर

इसके अलावा, @GeoffPatterson ने बताया, क्या मैं इसका उपयोग नहीं कर सकता हूं COALESCE? मैं इसे क्यों रखूंगा?
डेविड फेइवर

@ डेविड आप शायद छोड़ सकते हैं COALESCE। मैंने आपके मूल कोड के लुक और इरादे को बनाए रखने की कोशिश की, और इसके बिना परीक्षण नहीं किया, ताकि परीक्षण आप पर हो। (मैं तुम क्यों था व्याख्या कर सकते हैं नहीं ISNULLपहले स्थान में, या तो।)
हारून बर्ट्रेंड

5

यह SQL सर्वर कंप्यूटेड कॉलम लॉजिक लॉजिक की एक विशिष्ट सीमा है, जब सबसे बाहरी ISNULLउपयोग किया जाता है, और कॉलम का डेटाटाइप होता है bit

बग रिपोर्ट

समस्या से बचने के लिए, निम्नलिखित में से कोई भी कार्यस्थल नियोजित किया जा सकता है:

  1. एक बाहरीतम ISNULL(एक संगणित कॉलम बनाने का एकमात्र तरीका NOT NULL) का उपयोग न करें ।
  2. bitडेटा प्रकार का उपयोग गणना कॉलम के अंतिम प्रकार के रूप में न करें ।
  3. कंप्यूटेड कॉलम बनायें PERSISTEDऔर ट्रेस फ्लैग 174 को सक्षम करें

विवरण

मुद्दे का दिल यह है कि ट्रेस फ्लैग 174 के बिना, क्वेरी में सभी संगणित स्तंभ संदर्भ (यहां तक ​​कि निरंतर) हमेशा क्वेरी संकलन में बहुत जल्दी अंतर्निहित परिभाषा में विस्तारित होते हैं।

विस्तार का विचार यह है कि यह सरलीकरण और पुनर्लेखन को सक्षम कर सकता है जो केवल परिभाषा पर काम कर सकता है, अकेले स्तंभ नाम पर नहीं। उदाहरण के लिए, गणना संदर्भित कॉलम में गणना में बेमानी हो सकती है, जो गणना के भाग को अनावश्यक बना सकती है, या अन्यथा अधिक विवश हो सकती है।

एक बार जब प्रारंभिक सरलीकरण और पुनर्लेखन पर विचार किया जाता है, तो क्वेरी संकलन संकलन कॉलम में सभी भावों (सभी गणना किए गए कॉलम, जो मूल रूप से क्वेरी टेक्स्ट में पाए जाते हैं, न केवल) में अभिव्यक्तियों से मेल खाने का प्रयास करते हैं।

अपरिवर्तित गणना किए गए स्तंभ अभिव्यक्तियाँ अधिकांश मामलों में समस्या के बिना मूल गणना किए गए स्तंभ से मेल खाती हैं। एक बग प्रतीत होता है जब एक अभिव्यक्ति के मिलान के लिए विशिष्ट होता है bit, सबसे बाहरी के साथ ISNULL। इस विशिष्ट मामले में मिलान असफल है, यहां तक ​​कि जहां आंतरिक की एक विस्तृत परीक्षा से पता चलता है कि इसे सफल होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.