2013-07-25 8 views
12

हमारे डेटाबेस में हम 200.000 पंक्तियोंमेरी अनुक्रमणिका का उपयोग कर SQL सर्वर क्यों नहीं है?

CREATE TABLE dbo.UserTask (
    UserTask_ID int NOT NULL IDENTITY (1, 1), 
    UserTask_SequenceNumber int NOT NULL DEFAULT 0, 
    UserTask_IdEntitat uniqueidentifier NOT NULL, 
    UserTask_Subject varchar(100) NOT NULL, 
    UserTask_Description varchar(500) NOT NULL, 
      ..... 
      ..... 
    CONSTRAINT [PK_UserTask] PRIMARY KEY CLUSTERED 
    (
     [UserTask_ID] ASC 
    ) ON [PRIMARY] 
) ON [PRIMARY] 

के साथ इस तालिका मैं

CREATE NONCLUSTERED INDEX IX_UserTask_IDEntitat ON dbo.UserTask 
(
    UserTask_IDEntitat 
) 

निम्न क्वेरी निष्पादित साथ UserTask_IdEntitat स्तंभ पर एक सूचकांक बनाया है, कार्य योजना लागू करके हमें UserTask_IDEntitat पर कि सूचकांक प्रयोग किया जाता है पता चलता क्वेरी करने के लिए:

SELECT UserTask_ID 
    FROM UserTask 
WHERE UserTask_IdEntitat = @IdEntitat 
ORDER BY UserTask_LastSendSystemDateTime desc 

लेकिन अगर हममें एक और कॉलम जोड़ते हैंसूची है, तो सूचकांक

SELECT UserTask_ID, UserTask_SequenceNumber, UserTask_IDEntitat, ....., UserTask_Subject 
    FROM UserTask 
WHERE UserTask_IdEntitat = @IdEntitat 
ORDER BY UserTask_LastSendSystemDateTime desc 

नहीं किया जाता है क्यों जोड़ने एक स्तंभ प्राथमिक कुंजी से अलग बनाता है कि एसक्यूएल सर्वर कार्य योजना लागू करके UserTask_IDEntitat स्तंभ पर सूचकांक का उपयोग नहीं करता?

इस लिंक के बाद http://bytes.com/topic/sql-server/answers/144592-sqlsever-not-using-index ऐसा लगता है कि फ़िल्टर किए गए मान को कॉलम पर दोहराया गया है, यह बना सकता है कि इंडेक्स का उपयोग नहीं किया जाता है, लेकिन मैंने @IdEntitat मान के साथ क्वेरी करने का प्रयास किया है जो दोहराया जाता है 60,000 बार और अन्य जो केवल 175 बार दोहराया जाता है और परिणाम समान होते हैं, IDEntitat कॉलम पर सूचकांक अनदेखा किया जाता है।

यह मुझे पागल ले रहा है !!!

आपकी मदद के लिए धन्यवाद।

+3

आप एक उपयुक्त संस्करण पर हैं, और यह एक आम प्रश्न है, तो आप 'शामिल करने पर विचार करना चाह सकते हैं सूचकांक में '_SequenceNumber'' 'ing। –

+0

... और 'LastSendSystemDateTime' भी, मुझे लगता है। ('द्वारा आदेश 'करने में मदद करने के लिए)। –

उत्तर

32

ठीक है - आप केवल स्तंभ सूचकांक में है कि, या क्लस्टरिंग कुंजी (आमतौर पर, इस प्राथमिक कुंजी है) से कुछ का चयन के रूप में रूप में लंबे समय है, तो सूचकांक हो जाएगा प्रयुक्त, चूंकि SQL सर्वर इंडेक्स नेविगेशन संरचना के पत्ते के स्तर में आवश्यक सभी जानकारी (UserTask_IDEntitat कॉलम, और क्लस्टरर्ड इंडेक्स कॉलम) ढूंढ सकता है। तो यह सूचकांक के पत्ते स्तर पृष्ठों से सीधे SELECT क्वेरी के लिए आवश्यक डेटा वापस कर सकता है।

हालांकि: यदि आप एक दूसरे स्तंभ का चयन करने की जरूरत है, कि न सूचकांक परिभाषा, है और न ही क्लस्टरिंग कुंजी हिस्सा है, तो SQL सर्वर एक तथाकथित बुकमार्क देखने क्या करना है होता है वास्तविक डेटा पृष्ठों में

तो हर एक पंक्ति के लिए यह अपने nonclustered अनुक्रमणिका में पाता है, यह, क्लस्टरिंग इंडेक्स मान लेने के लिए, खोज क्लस्टर सूचकांक कि संकुल अनुक्रमणिका की पत्ती स्तर पर वास्तविक डेटा पेज को खोजने के लिए होता है और फिर उस कॉलम को चुनें जिसे आप चाहते हैं।

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

तो: यदि आप UserTask_IDEntitat पर एक सूचकांक है और आप कभी कभी भी एक दूसरे स्तंभ UserTask_SequenceNumber की जरूरत है - तो आप शामिल हो सकते हैं कि तुम्हारा कि nonclustered अनुक्रमणिका में स्तंभ:

CREATE NONCLUSTERED INDEX IX_UserTask_IDEntitat 
ON dbo.UserTask(UserTask_IDEntitat) 
INCLUDE(UserTask_SequenceNumber) 
इस के साथ

, कि अतिरिक्त कॉलम पत्ती के स्तर में केवल उस गैर-क्लस्टर सूचकांक में मौजूद है (इसे WHERE खंड में उपयोग नहीं किया जा सकता है - यह इंडेक्स की नेविगेशन संरचना का हिस्सा नहीं है!) - और आपका दूसरा SELECT फिर से पत्ते से संतुष्ट हो सकता है नॉनक्लस्टर्ड इंडेक्स के -वेल नोड्स -> कोई पूर्व नहीं गहन बुकमार्क लुकअप की आवश्यकता है -> आपकी अनुक्रमणिका का फिर से उपयोग किया जाएगा।

लंबी कहानी कम: जब तक आपके nonclustered अनुक्रमणिका है अत्यधिक चयनात्मक (जैसे अपनी पंक्तियों या उससे कम की 1% रिटर्न), और जब तक आपके nonclustered अनुक्रमणिका एक कवर सूचकांक (एक सूचकांक कि सभी शामिल है कॉलम को किसी विशेष क्वेरी को संतुष्ट करने के लिए आवश्यक), तो परिवर्तन बहुत अधिक हैं कि SQL सर्वर नहीं आपके गैर-क्लस्टर इंडेक्स का उपयोग करेगा।

अधिक जानकारी लिए :

+0

आपके विस्तृत उत्तर और आपके उपयोगी लिंक के लिए धन्यवाद, मुझे वास्तव में उत्पादन प्रश्नों में क्या चाहिए, केवल उपयोगकर्ताTask_SequenceNumber को वापस नहीं लौटाता है, मुझे सभी कॉलम वापस करने की आवश्यकता है, (दूसरी क्वेरी यह एक बुरा उदाहरण था), इस मामले में ऐसा नहीं है करने के लिए कोई आसान अनुकूलन, नहीं? SqlServer सबसे प्रभावी तरीका कर रहा है संभव है। –

+2

@MarcCals: यदि आपको ** सभी ** कॉलम की आवश्यकता है - तो अधिकांश समय, इंडेक्स वास्तव में मदद नहीं करेगा क्योंकि क्लस्टर्ड इंडेक्स स्कैन करना आमतौर पर हजारों महंगे बुकमार्क लुकअप करने से अधिक कुशल होता है –

2

आप इंडेक्स का उपयोग करने के लिए क्वेरी में क्वेरी संकेतों का उपयोग कर सकते हैं। के बाद अधिक जानकारी के लिए एक कड़ी है: http://msdn.microsoft.com/en-us/library/ms181714.aspx

संबंधित मुद्दे