CASE के साथ एक SUM से अधिक COUNT तेज़ी से क्यों हैं?


14

मैं जानना चाहता था कि निम्नलिखित दो दृष्टिकोणों में से कौन सा तेज़ है:

1) तीन COUNT:

 SELECT Approved = (SELECT COUNT(*) FROM dbo.Claims d
                  WHERE d.Status = 'Approved'),
        Valid    = (SELECT COUNT(*) FROM dbo.Claims d
                    WHERE d.Status = 'Valid'),
        Reject   = (SELECT COUNT(*) FROM dbo.Claims d
                    WHERE d.Status = 'Reject')

2) SUMके साथ FROM-clause:

SELECT  Approved = SUM(CASE WHEN Status = 'Approved' THEN 1 ELSE 0 END),
        Valid    = SUM(CASE WHEN Status = 'Valid'    THEN 1 ELSE 0 END),
        Reject   = SUM(CASE WHEN Status = 'Reject'   THEN 1 ELSE 0 END)
FROM dbo.Claims c;

मुझे आश्चर्य हुआ कि अंतर इतना बड़ा है। तीन उपश्रेणियों वाली पहली क्वेरी तुरंत परिणाम देती है जबकि दूसरे SUMदृष्टिकोण को 18 सेकंड की आवश्यकता होती है।

Claimsएक दृश्य है जो ~ 18 मिलियन पंक्तियों वाली तालिका से चयन करता है। FK-Column में ClaimStatusटेबल पर एक इंडेक्स होता है जिसमें स्टेटस-नाम होता है।

यह इतना बड़ा अंतर क्यों करता है कि मैं उपयोग करता हूं COUNTया SUM?

निष्पादन-योजनाओं:

कुल 12 स्थितियां हैं। उन तीन स्थितियों में सभी पंक्तियों का 7% हिस्सा है।


यह वास्तविक दृश्य है, मुझे यकीन नहीं है कि यह प्रासंगिक है:

CREATE VIEW [dbo].[Claims]
AS
SELECT 
   mu.Marketunitname AS MarketUnit, 
   c.Countryname     AS Country, 
   gsp.Gspname       AS GSP, 
   gsp.Wcmskeynumber AS GspNumber, 
   sl.Slname         AS SL, 
   sl.Wcmskeynumber  AS SlNumber, 
   m.Modelname       AS Model, 
   m.Salesname       AS [Model-Salesname], 
   s.Claimstatusname AS [Status], 
   d.Work_order      AS [Work Order], 
   d.Ssn_number      AS IMEI, 
   d.Ssn_out, 
   Remarks, 
   d.Claimnumber     AS [Claim-Number], 
   d.Rma_number      AS [RMA-Number], 
   dbo.ToShortDateString(d.Received_Date, 1) AS [Received Date], 
   Iddata, 
   Fisl, 
   Fimodel, 
   Ficlaimstatus 
FROM Tabdata AS d 
   INNER JOIN Locsl AS sl 
           ON d.Fisl = sl.Idsl 
   INNER JOIN Locgsp AS gsp 
           ON sl.Figsp = gsp.Idgsp 
   INNER JOIN Loccountry AS c 
           ON gsp.Ficountry = c.Idcountry 
   INNER JOIN Locmarketunit AS mu 
           ON c.Fimarketunit = mu.Idmarketunit 
   INNER JOIN Modmodel AS m 
           ON d.Fimodel = m.Idmodel 
   INNER JOIN Dimclaimstatus AS s 
           ON d.Ficlaimstatus = s.Idclaimstatus 
   INNER JOIN Tdefproducttype 
           ON d.Fiproducttype = Tdefproducttype.Idproducttype 
   LEFT OUTER JOIN Tdefservicelevel 
                ON d.Fimaxservicelevel = Tdefservicelevel.Idservicelevel 
   LEFT OUTER JOIN Tdefactioncode AS ac 
                ON d.Fimaxactioncode = ac.Idactioncode 

यह दोनों लिंक COUNTयोजना के संस्करण की ओर इशारा करता है । क्या आप SUMसही योजना को इंगित करने के लिए संस्करण की तरह संपादित कर सकते हैं ?
ज्योफ पैटरसन 14

अन्य स्टेटियों वाली पंक्तियों की तुलना में उन तीन स्टेटियों के साथ पंक्तियों का अनुपात क्या है?
मैक्स वर्नोन

1
@MaxVernon: हाँ, निश्चित रूप से, मैंने बहुत सारे शून्य देखे हैं, आप सही हैं। मुझे अपनी टिप्पणियों को हटाने दें। हाँ, अन्य स्थिति में 16.7 मिलियन पंक्तियाँ हैं। ज्यादातर हैं Authorized
बजे टिम शाल्टर

2
मुझे लगता है कि दूसरी योजना पूरे टेबल को 12 बार स्कैन करने से पीड़ित है (जो कि दिखाता है)। यह संभावना है कि स्कैन में विधेय को नीचे धकेलने में सक्षम नहीं है। जैसा कि आप जोड़ने के प्रदर्शन कैसा है WHERE c.Status = 'Approved' or c.Status = 'Valid' or c.status = 'Reject'करने के लिए SUMसंस्करण।
मैक्स वर्नोन

@MaxVernon: कुल बारह स्थितियाँ हैं। यह वास्तव में मेरे लिए कोई मुद्दा नहीं है, लेकिन मैं बहुत हैरान था कि आशावादी इसे संभाल नहीं सकता है। मुझे वास्तव में अपने निष्पादन-योजना विश्लेषण कौशल पर काम करना चाहिए। इसका उत्तर बनाओ। आपकी धारणा क्या है, SQL- सर्वर केवल तीन स्थितियों को स्कैन करने में सक्षम क्यों नहीं है?
टिम शिलेटर

जवाबों:


19

COUNT(*)संस्करण जबकि, एक बार प्रत्येक स्थिति आप चयन कर रहे हैं के लिए बस सूचकांक आप स्थिति कॉलम पर है में की तलाश करने में सक्षम है SUM(...)संस्करण जरूरतों सूचकांक बारह बार (अद्वितीय स्थितियां कई प्रकार की कुल संख्या) की तलाश के लिए।

स्पष्ट रूप से तीन बार एक सूचकांक की मांग 12 बार की तुलना में तेजी से होने जा रही है।

पहले प्लान के लिए 238MB मेमोरी मेमोरी की आवश्यकता होती है, जबकि दूसरी योजना के लिए 650MB मेमोरी मेमोरी की आवश्यकता होती है। यह हो सकता है कि बड़ा मेमोरी ग्रांट तुरंत भरा न जा सके, जिससे क्वेरी बहुत धीमी हो जाए।

दूसरी क्वेरी को बदल दें:

SELECT  Approved = SUM(CASE WHEN Status = 'Approved' THEN 1 ELSE 0 END),
        Valid    = SUM(CASE WHEN Status = 'Valid'    THEN 1 ELSE 0 END),
        Reject   = SUM(CASE WHEN Status = 'Reject'   THEN 1 ELSE 0 END)
FROM dbo.Claims c
WHERE c.Status = 'Approved'
    OR c.Status = 'Valid'
    OR c.Status = 'Reject';

यह क्वेरी ऑप्टिमाइज़र को अनुक्रमणिका का 75% हिस्सा समाप्त करने की अनुमति देगा, और इसके परिणामस्वरूप कम आवश्यक मेमोरी अनुदान, कम I / O आवश्यकताएं और तेजी से समय-समय पर परिणाम होना चाहिए।

SUM(CASE WHEN ...)निर्माण अनिवार्य रूप से आगे बढ़ाने से क्वेरी अनुकूलक रोकता Statusसूचकांक में विधेय नीचे योजना के हिस्से की तलाश है।


स्मृति के साथ अच्छी पकड़ है। मैंने देखा है कि मेरे सभी 32 जीबी वर्तमान में उपयोग में हैं (केवल 300 एमबी मुफ्त)। हालाँकि संपादित करें , मैंने कुछ मेमोरी को मुक्त कर दिया है। परिणाम वही है
टिम श्मेल्टर

आप max server memoryविकल्प को देखना चाहते हैं - इसे आपके सिस्टम के लिए सही मान में कॉन्फ़िगर किया जाना चाहिए। आप इस प्रश्न और विवरण के उत्तरों को देखना चाहते हैं कि यह कैसे करना है।
मैक्स वर्नोन

1
दुर्भाग्य से यह सर्वर न केवल डेटाबेस के लिए उपयोग किया जाता है, बल्कि एसएसएएस क्यूब और कुछ टूल (इंट्रानेट वेब-ऐप सहित) के लिए भी उपयोग किया जाता है। लेकिन मैंने पहले ही 12GB को अधिकतम के रूप में सौंपा है।
टिम शाल्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.