सूचकांक तेजी से निष्पादन नहीं कर रहा है, और कुछ मामलों में क्वेरी को धीमा कर रहा है। ऐसा क्यों है?


34

मैं चीजों को गति देने के लिए अनुक्रमित के साथ प्रयोग कर रहा था, लेकिन एक जुड़ने की स्थिति में, सूचकांक क्वेरी निष्पादन समय में सुधार नहीं कर रहा है और कुछ मामलों में यह चीजों को धीमा कर रहा है।

परीक्षण तालिका बनाने और उसे डेटा से भरने की क्वेरी है:

CREATE TABLE [dbo].[IndexTestTable](
    [id] [int] IDENTITY(1,1) PRIMARY KEY,
    [Name] [nvarchar](20) NULL,
    [val1] [bigint] NULL,
    [val2] [bigint] NULL)

DECLARE @counter INT;
SET @counter = 1;

WHILE @counter < 500000
BEGIN
    INSERT INTO IndexTestTable
      (
        -- id -- this column value is auto-generated
        NAME,
        val1,
        val2
      )
    VALUES
      (
        'Name' + CAST((@counter % 100) AS NVARCHAR),
        RAND() * 10000,
        RAND() * 20000
      );

    SET @counter = @counter + 1;
END

-- Index in question
CREATE NONCLUSTERED INDEX [IndexA] ON [dbo].[IndexTestTable]
(
    [Name] ASC
)
INCLUDE (   [id],
    [val1],
    [val2])

अब क्वेरी 1, जिसमें सुधार किया गया है (केवल थोड़ा लेकिन सुधार सुसंगत है):

SELECT *
FROM   IndexTestTable I1
       JOIN IndexTestTable I2
            ON  I1.ID = I2.ID
WHERE  I1.Name = 'Name1'

सूचकांक के बिना आँकड़े और निष्पादन योजना (इस मामले में तालिका डिफ़ॉल्ट क्लस्टर किए गए सूचकांक का उपयोग करती है):

(5000 row(s) affected)
Table 'IndexTestTable'. Scan count 2, logical reads 5580, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 109 ms,  elapsed time = 294 ms.

यहाँ छवि विवरण दर्ज करें

अब इंडेक्स सक्षम होने के साथ:

(5000 row(s) affected)
Table 'IndexTestTable'. Scan count 2, logical reads 2819, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 94 ms,  elapsed time = 231 ms.

यहाँ छवि विवरण दर्ज करें

अब वह क्वेरी जो इंडेक्स के कारण धीमी हो जाती है (क्वेरी अर्थहीन है क्योंकि यह केवल परीक्षण के लिए बनाई गई है):

SELECT I1.Name,
       SUM(I1.val1),
       SUM(I1.val2),
       MIN(I2.Name),
       SUM(I2.val1),
       SUM(I2.val2)
FROM   IndexTestTable I1
       JOIN IndexTestTable I2
            ON  I1.Name = I2.Name
WHERE   
       I2.Name = 'Name1'
GROUP BY
       I1.Name

क्लस्टर किए गए सूचकांक के साथ सक्षम:

(1 row(s) affected)
Table 'IndexTestTable'. Scan count 4, logical reads 60, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 1, logical reads 155106, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 17207 ms,  elapsed time = 17337 ms.

यहाँ छवि विवरण दर्ज करें

अब सूचकांक अक्षम के साथ:

(1 row(s) affected)
Table 'IndexTestTable'. Scan count 5, logical reads 8642, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 165212, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 17691 ms,  elapsed time = 9073 ms.

यहाँ छवि विवरण दर्ज करें

प्रश्न हैं:

  1. हालांकि SQL सर्वर द्वारा इंडेक्स का सुझाव दिया गया है, लेकिन यह महत्वपूर्ण अंतर से चीजों को धीमा क्यों करता है?
  2. नेस्टड लूप क्या है जो अधिकांश समय ले रहा है और इसके निष्पादन समय को कैसे बेहतर बनाया जाए?
  3. क्या ऐसा कुछ है जो मैं गलत कर रहा हूं या छूट गया है?
  4. डिफ़ॉल्ट इंडेक्स के साथ (केवल प्राथमिक कुंजी पर) इसमें कम समय क्यों लगता है, और नॉन क्लस्टर्ड इंडेक्स के साथ, उपस्थित तालिका में प्रत्येक पंक्ति के लिए, सम्मिलित तालिका पंक्ति को त्वरित रूप से पाया जाना चाहिए, क्योंकि शामिल होने पर नाम स्तंभ पर है सूचकांक बनाया गया है। इंडेक्स एक्ट सक्रिय होने पर यह क्वेरी एक्जीक्यूशन प्लान और इंडेक्स सीक कॉस्ट में कम परिलक्षित होता है, लेकिन फिर भी धीमा क्यों है? इसके अलावा नेस्टेड लूप में जो बाहरी जुड़ाव है वह मंदी का कारण है?

SQL सर्वर 2012 का उपयोग करना

जवाबों:


23

हालांकि SQL सर्वर द्वारा इंडेक्स का सुझाव दिया गया है, लेकिन यह महत्वपूर्ण अंतर से चीजों को धीमा क्यों करता है?

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

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

नेस्टड लूप क्या है जो अधिकांश समय ले रहा है और इसके निष्पादन समय को कैसे बेहतर बनाया जाए?

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

क्या ऐसा कुछ है जो मैं गलत कर रहा हूं या छूट गया है?

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

स्कैन योजना

गैर-अनुक्रमित इंडेक्स सीक का उपयोग करने की योजना में, कार्य पूरी तरह से एक धागे से किया जा रहा है:

योजना की तलाश करें

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

थ्रेड्स के बीच पंक्ति वितरण को प्रभावित करने के लिए कोई क्वेरी संकेत नहीं हैं, महत्वपूर्ण बात यह है कि संभावना के बारे में पता होना और निष्पादन योजना में पर्याप्त विवरण पढ़ने में सक्षम होना यह निर्धारित करने के लिए कि यह समस्या पैदा कर रहा है।

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

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

उदाहरण को पूरा करने और मेरे द्वारा बताई गई कुछ चीजों को दर्शाने के लिए, एक बेहतर कार्य वितरण प्राप्त करने का एक तरीका यह है कि समानांतर निष्पादन को चलाने के लिए एक अस्थायी तालिका का उपयोग किया जाए:

SELECT
    val1,
    val2
INTO #Temp
FROM dbo.IndexTestTable AS ITT
WHERE Name = N'Name1';

SELECT 
    N'Name1',
    SUM(T.val1),
    SUM(T.val2),
    MIN(I2.Name),
    SUM(I2.val1),
    SUM(I2.val2)
FROM   #Temp AS T
CROSS JOIN IndexTestTable I2
WHERE
    I2.Name = 'Name1'
OPTION (FORCE ORDER, QUERYTRACEON 8690);

DROP TABLE #Temp;

यह एक ऐसी योजना का परिणाम है जो अधिक कुशल सूचकांक का उपयोग करता है, एक टेबल स्पूल की सुविधा नहीं देता है, और थ्रेड्स में काम को अच्छी तरह से वितरित करता है:

इष्टतम योजना

मेरे सिस्टम पर, यह योजना क्लस्टर्ड इंडेक्स स्कैन संस्करण की तुलना में बहुत तेजी से निष्पादित होती है।

यदि आप समानांतर क्वेरी निष्पादन के इंटर्न के बारे में अधिक जानने में रुचि रखते हैं, तो आप मेरी PASS समिट 2013 सत्र रिकॉर्डिंग देखना पसंद कर सकते हैं ।


0

यह वास्तव में सूचकांक का सवाल नहीं है, यह अधिक बुरी तरह से लिखित क्वेरी है। आपके पास नाम के केवल 100 अद्वितीय मूल्य हैं, यह प्रति नाम 5000 की एक अद्वितीय गणना छोड़ देता है।

तो तालिका 1 में प्रत्येक पंक्ति के लिए आप तालिका 2 से 5000 में शामिल हो रहे हैं। क्या आप 25020004 पंक्तियाँ कह सकते हैं।

यह कोशिश करो, ध्यान दें कि यह केवल 1 सूचकांक के साथ है, जिसे आपने सूचीबद्ध किया है।

    DECLARE @Distincts INT
    SET @Distincts = (SELECT  TOP 1 COUNT(*) FROM IndexTestTable I1 WHERE I1.Name = 'Name1' GROUP BY I1.Name)
    SELECT I1.Name
    , @Distincts
    , SUM(I1.val1) * @Distincts
    , SUM(I1.val2) * @Distincts
    , MIN(I2.Name)
    , SUM(I2.val1)
    , SUM(I2.val2)
    FROM   IndexTestTable I1
    LEFT OUTER JOIN

    (
        SELECT I2.Name
        , SUM(I2.val1) val1
        , SUM(I2.val2) val2
        FROM IndexTestTable I2
        GROUP BY I2.Name
    ) I2 ON  I1.Name = I2.Name
    WHERE I1.Name = 'Name1'
    GROUP BY  I1.Name

और समय:

    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 8 ms.
    Table 'IndexTestTable'. Scan count 1, logical reads 31, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 1 ms.

    (1 row(s) affected)
    Table 'IndexTestTable'. Scan count 2, logical reads 62, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     SQL Server Execution Times:
       CPU time = 16 ms,  elapsed time = 10 ms.

यहाँ छवि विवरण दर्ज करें

आप बुरी तरह से निर्मित प्रश्नों के लिए SQL इंडेक्स को दोष नहीं दे सकते


1
उत्तर के लिए धन्यवाद, और हाँ क्वेरी में सुधार किया जा सकता है, लेकिन मेरे सवाल का तर्क यह था कि डिफ़ॉल्ट इंडेक्स (केवल प्राथमिक कुंजी पर) इसमें कम समय क्यों लगता है, और मौजूद गैर-संकुल इंडेक्स के साथ, प्रत्येक पंक्ति के लिए ज्वाइनिंग टेबल, ज्वाइन टेबल रो को जल्दी मिल जाना चाहिए, जो कि क्वेरी एक्जीक्यूशन प्लान में परिलक्षित होता है और IndexA के सक्रिय होने पर Index Seek cost कम होती है, लेकिन फिर भी धीमी क्यों होती है? इसके अलावा नेस्टेड लूप में जो बाहरी जुड़ाव है वह मंदी का कारण है? मैंने इस टिप्पणी को जोड़ने के लिए प्रश्न को संपादित किया है, ताकि प्रश्न अधिक स्पष्ट हो सके।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.