কেন একাধিক COUNT টি CASE এর সাথে এক SUM এর চেয়ে দ্রুত?


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 সেকেন্ডের প্রয়োজন হয় needs

Claimsএমন একটি দৃশ্য যা 18 মিলিয়ন ডলার সারি যুক্ত একটি টেবিল থেকে নির্বাচন করে। 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সঠিক পরিকল্পনার দিকে ইঙ্গিত করতে সংস্করণটির মতো পছন্দগুলি সম্পাদনা করতে পারেন ?
জিফ প্যাটারসন

অন্যান্য স্টাটির সাথে সারিগুলির তুলনায় এই তিনটি স্তরের সাথে সারিগুলির অনুপাত কত?
ম্যাক্স ভার্নন

1
@ ম্যাক্স ভার্নন: হ্যাঁ, অবশ্যই আমি অনেকগুলি শূন্য দেখেছি, আপনি ঠিক বলেছেন। আমাকে আমার মন্তব্য মুছে দিন। হ্যাঁ, অন্য স্থিতিতে 16.7 মিলিয়ন সারি রয়েছে। সর্বাধিক হয় Authorized
টিম শ্মেলেটার

2
আমি অনুমান করব যে দ্বিতীয় পরিকল্পনায় পুরো টেবিলটি 12 বার স্ক্যান করার কারণে ভুগছে ( এটি সম্ভবত ভবিষ্যদ্বাণীগুলিকে স্ক্যানের দিকে ঠেলে দিতে না পেরে আসছে। পারফরম্যান্স কেমন হয় যদি আপনি বৈকল্পটিতে যুক্ত WHERE c.Status = 'Approved' or c.Status = 'Valid' or c.status = 'Reject'হন SUM
ম্যাক্স ভার্নন

@ ম্যাক্স ভার্নন: মোট বারোটি স্ট্যাটাস রয়েছে। এটি আমার পক্ষে আসলেই কোনও সমস্যা নয়, তবে আমি খুব উদ্বিগ্ন ছিলাম যে অপটিমাইজার এটি পরিচালনা করতে পারে না। আমার বাস্তবায়ন পরিকল্পনাটি দক্ষতার বিশ্লেষণে সত্যই আমার কাজ করা উচিত। এটি একটি উত্তর করুন। আপনার অনুমান কী, এসকিউএল-সার্ভার কেন কেবল তিনটি স্ট্যাটাস স্ক্যান করতে সক্ষম নয়?
টিম শ্মেলটার

উত্তর:


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সূচক মধ্যে predicates নিচে পরিকল্পনার অংশ চাইতে।


স্মৃতির সাথে ভালো লাগছে। আমি লক্ষ্য করেছি যে আমার ৩২ জিবি এর সমস্ত বর্তমানে ব্যবহারে রয়েছে (কেবল ৩০০ এমবি নিখরচায়)। সম্পাদনা যাইহোক, আমি কিছু স্মৃতি মুক্ত করেছি। ফলাফল একই
টিম শ্মেলটার

আপনি max server memoryবিকল্পটি দেখতে চাইতে পারেন - এটি আপনার সিস্টেমে সঠিক মান হিসাবে কনফিগার করা উচিত। আপনি এই প্রশ্নটি এবং এটি কীভাবে করবেন তার বিশদগুলির জন্য উত্তরগুলি দেখতে চাইতে পারেন ।
ম্যাক্স ভার্নন

1
দুর্ভাগ্যক্রমে এই সার্ভারটি কেবল ডাটাবেসের জন্যই নয়, এসএসএএস কিউব এবং কিছু সরঞ্জামগুলির জন্য (ইন্ট্রানেট ওয়েব অ্যাপ্লিকেশন সহ) ব্যবহৃত হয়। তবে আমি ইতিমধ্যে সর্বোচ্চ 12 জিবি বরাদ্দ করেছি।
টিম শ্মেলেটার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.