ফাংশন নাল কেস অপারেশন সঙ্গে স্তব্ধ


9

আমি একটি ফাংশন তৈরি করেছি যা শুরু এবং শেষের তারিখটি alচ্ছিকভাবে গ্রহণ করে। তারপরে আমি CASEকোনও শেষের তারিখটি পাস না করা হলে শুরুর তারিখটি ব্যবহার করতে ফিল্টারটিতে একটি লিখেছিলাম ।

CASE WHEN @dateEnd IS NULL
    THEN @dateStart
    ELSE @dateEnd
END

আমি যখন ডেটার সবচেয়ে সাম্প্রতিক মাসের জন্য ফাংশনটি কল করি:

SELECT * FROM theFunction ('2013-06-01', NULL)

... ক্যোয়ারি ঝুলছে। যদি আমি শেষের তারিখটি নির্দিষ্ট করি:

SELECT * FROM theFunction ('2013-06-01', '2013-06-01')

... ফলাফলটি সাধারণত ফিরে আসে। আমি কোডটি ফাংশনটির বাইরে নিয়ে এসে এটিকে একটি কোয়েরি উইন্ডোর ভিতরে দৌড়েছি। আমি ইস্যুটির মূর্খতাটিও নকল করতে পারি না। এর মতো একটি কোয়েরি:

SELECT * FROM theFunction ('2013-04-01', '2013-06-01')

... ভাল কাজ করে।

কোয়েরিতে (নীচে) এমন কিছু আছে NULLযা শেষ তারিখের জন্য পাস করার পরে ফাংশনটি স্তব্ধ হয়ে যেতে পারে ?

এসকিউএল ফিডল


আপনি কি আরও যুক্তি পোস্ট করতে পারেন? আপনার যা আছে তা সমস্যার কারণ হবে না।
কেনেথ ফিশার 0

3
আপনি যদি এর CASEসাথে প্রতিস্থাপন করেন COALESCE(@dateEnd,@dateStart), তবে কি সমস্যাটি এখনও উপস্থিত হয়?
ypercubeᵀᴹ

2
আর সাথে ISNULL()?
ypercubeᵀᴹ

3
এটি ব্যস্ত বা কিছু অপেক্ষা করা হয়? এটি "স্তব্ধ" থাকলে কী SELECT task_state FROM sys.dm_os_tasks WHERE session_id = x দেখায়? এটি যদি RUNNINGরাজ্যে না অনেক সময় ব্যয় করে তবে সেই অধিবেশনটি কী ধরণের অপেক্ষা অপেক্ষা করছে sys.dm_os_waiting_tasks?
মার্টিন স্মিথ

1
@ypercube সহ কোনো উন্নতি COALESCEISNULLঠিক কর.
কেরমিট

উত্তর:


7

আপনার প্রাথমিক ক্যোয়ারির অংশটি নিম্নরূপ।

  FROM   [dbo].[calendar] a
          LEFT JOIN [dbo].[colleagueList] b
            ON b.[Date] = a.d
   WHERE  DAY(a.[d]) = 1
          AND a.[d] BETWEEN @dateStart AND COALESCE(@dateEnd,@dateStart) 

পরিকল্পনার সেই অংশটি নীচে দেখানো হয়েছে

এখানে চিত্র বর্ণনা লিখুন

আপনার সংশোধিত প্রশ্নের BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)সাথে একই যোগদানের জন্য এটি রয়েছে

এখানে চিত্র বর্ণনা লিখুন

পার্থক্যটি মনে হয় যা ISNULLআরও সরল করে তোলে এবং ফলস্বরূপ আপনি আরও সঠিক কার্ডিনালিটির পরিসংখ্যানগুলি পরবর্তী জোড়ায় যাবেন। এটি একটি ইনলাইন টেবিলের মূল্যবান ফাংশন এবং আপনি এটি আক্ষরিক মান সহ কল ​​করছেন যাতে এটি এর মতো কিছু করতে পারে।

 a.[d] BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart) 
 a.[d] BETWEEN '2013-06-01' AND ISNULL(NULL,'2013-06-01') 
 a.[d] BETWEEN '2013-06-01' AND '2013-06-01'
 a.[d] = '2013-06-01'

ইক্যুইতে যোগ দেওয়ার পূর্বে হস্তক্ষেপ b.[Date] = a.dকরার পরিকল্পনাটিও সমতার পূর্ববর্তী দেখায় b.[Date] = '2013-06-01'। ফলস্বরূপ 28,393সারিগুলির কার্ডিনালিটির প্রাক্কলনটি সম্ভবত বেশ নির্ভুল হতে পারে।

জন্য CASE/ COALESCEসংস্করণ যখন @dateStartএবং @dateEndএকই মান তারপর, এটা সহজসাধ্য একই সমতা এক্সপ্রেশন ঠিক আছ এবং একই পরিকল্পনা দেয় কিন্তু যখন @dateStart = '2013-06-01'এবং @dateEnd IS NULLএটি শুধুমাত্র যতদূর যায়

a.[d]>='2013-06-01' AND a.[Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END

এটি এটি একটি অন্তর্নিহিত ভবিষ্যদ্বাণী হিসাবেও প্রযোজ্য ColleagueList। এবার সারিগুলির আনুমানিক সংখ্যা হ'ল 79.8সারি।

পরবর্তী জোড় বরাবর হয়

   LEFT JOIN colleagueTime
     ON colleagueTime.TC_DATE = colleagueList.Date
        AND colleagueTime.ASSOC_ID = CAST(colleagueList.ID AS VARCHAR(10)) 

colleagueTimeএটি একটি 3,249,590সারি টেবিল যা (আবার) দৃশ্যত কোনও কার্যকর সূচী ছাড়াই apੇਰ।

অনুমানে এই তাত্পর্যটি ব্যবহৃত যোগদানের পছন্দকে প্রভাবিত করে। ISNULLপরিকল্পনা একটি হ্যাশ যোগদানের যে শুধু একবার টেবিল স্ক্যান পছন্দ করে। দ্যCOALESCEপরিকল্পনা একটি নেস্টেড loops যোগদানের বেছে এবং অনুমান যে এটা এখনও শুধু একবার টেবিল স্ক্যান এবং ফলাফলের নাটাই এবং 78 বার রিপ্লে পাবে প্রয়োজন হবে। অর্থাৎ এটি অনুমান করে যে পারস্পরিক সম্পর্কযুক্ত প্যারামিটারগুলি পরিবর্তন হবে না।

নেস্টেড লুপসের পরিকল্পনাটি এখনও দু'ঘন্টা পরেও চলেছিল এই ধরণের বিরুদ্ধে একটি একক স্ক্যানের অনুমান colleagueTime অত্যন্ত অসম্পূর্ণ বলে মনে হচ্ছে।

কেন দুই জনের মধ্যে সারিগুলির আনুমানিক সংখ্যার পরিমাণ এত কম, আমি টেবিলের পরিসংখ্যান দেখতে সক্ষম হওয়া ছাড়া নিশ্চিত নই। আমার পরীক্ষায় অনেকটাই সারি সংখ্যার তুলনায় আনুমানিক সারির সংখ্যাগুলিকে স্ক্যাঙ্ক করার জন্য পরিচালিত একমাত্র উপায় NULL(সারিগুলির আসল সংখ্যা একই থাকলেও এটি অনুমানযুক্ত সারির সংখ্যা হ্রাস পেয়েছে)।

COALESCEআমার পরীক্ষার ডেটা সহ পরিকল্পনার আনুমানিক সারি গণনাটি ছিল

number of rows matching >= condition * 30% * (proportion of rows in the table not null)

অথবা এসকিউএল-এ

SELECT 1E0 * COUNT([Date]) / COUNT(*) * ( COUNT(CASE
                                                  WHEN [Date] >= '2013-06-01' THEN 1
                                                END) * 0.30 )
FROM   [dbo].[colleagueList] 

তবে এটি আপনার মন্তব্যের সাথে বর্গক্ষেত্র নয় যে কলামটির কোনও NULLমূল্য নেই।


"সেই টেবিলের তারিখ কলামে আপনার কি নুল মানগুলির খুব বেশি অনুপাত রয়েছে?" আমি না NULLসেই টেবিল কোনো তারিখগুলি জন্য মান।
কেরমিট

@ ফ্রেশপ্রিন্সঅফসো - এটি দুঃখের বিষয়। তখনও দুটি অনুমানের মধ্যে এত বড় বৈষম্য কেন তা নিয়ে আমার এখনও ধারণা নেই। পরীক্ষাগুলিতে আমি বিটম্যাপ ফিল্টারটি করেছি এবং অতিরিক্ত প্রিকিকেট কার্ডিনালিটির অনুমানগুলি এখানে পরিবর্তন করে বলে মনে হয় না।
মার্টিন স্মিথ

@ ফ্রেশপ্রিন্সঅফসো - যদিও আপনি যদি পরিসংখ্যানগুলি লিপিবদ্ধ করার মতো মনে করেন তবে আমি চেষ্টা করে দেখতে পারব।
মার্টিন স্মিথ

আমি ২০০৮-এ থাকি; যখন আমি স্কিমাস বেছে নেব , dboতালিকাভুক্ত নয়। কেবলমাত্র অন্যান্য স্কিমা যা আমি ব্যবহার করি না।
কেরমিট

4

দেখে মনে হচ্ছে ডেটা ধরণের ক্ষেত্রে কোনও সমস্যা আছে। ISNULLসমস্যাটি স্থির করে (ধন্যবাদ ইপারকিউব )। কিছু গবেষণা করার পর, COALESCEসমতূল্য থেকে CASEবিবৃতি যে আমি ব্যবহার করা হয়েছে:

CASE
   WHEN (expression1 IS NOT NULL) THEN expression1
   WHEN (expression2 IS NOT NULL) THEN expression2
   ...
   ELSE expressionN
END

পল হোয়াইট ব্যাখ্যা করেছেন যে:

COALESCE( expression [ ,...n ] ) সর্বোচ্চ ডেটা টাইপের অগ্রাধিকার সহ এক্সপ্রেশনটির ডেটা টাইপ প্রদান করে।

ISNULL(check_expression, replacement_value) চেক_প্রকাশ হিসাবে একই ধরণের প্রত্যাবর্তন করে।

যে কোনও ডেটা ধরণের সমস্যা এড়াতে, ISNULLকেবল দুটি অভিব্যক্তি নিয়ে কাজ করার জন্য এটি উপযুক্ত ফাংশন বলে মনে হয়।

এক্সএমএল পরিকল্পনার অংশগুলি

এক্সএমএল পরিকল্পনাটি ব্যবহার করে CASEএক্সপ্রেশন 2 হ'ল NULL:

SELECT * FROM theFunction ('2013-06-01', NULL)
<ScalarOperator ScalarString="CASE WHEN (1) THEN '2013-06-01' ELSE NULL END">
  <IF>
    <Condition>
      <ScalarOperator>
        <Const ConstValue="(1)"/>
      </ScalarOperator>
    </Condition>
    <Then>
      <ScalarOperator>
        <Const ConstValue="'2013-06-01'"/>
      </ScalarOperator>
    </Then>
    <Else>
      <ScalarOperator>
        <Const ConstValue="NULL"/>
      </ScalarOperator>
    </Else>
  </IF>
</ScalarOperator>

এক্সএমএল প্ল্যান ব্যবহার করে CASEএক্সপ্রেশন 2 একটি তারিখ:

SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
<ScalarOperator ScalarString="CASE WHEN [Expr1035]=(0) THEN NULL ELSE [Expr1036] END">
  <IF>
    <Condition>
      <ScalarOperator>
        <Compare CompareOp="EQ">
          <ScalarOperator>
            <Identifier>
              <ColumnReference Column="Expr1035"/>
            </Identifier>
          </ScalarOperator>
          <ScalarOperator>
            <Const ConstValue="(0)"/>
          </ScalarOperator>
        </Compare>
      </ScalarOperator>
    </Condition>
    <Then>
      <ScalarOperator>
        <Const ConstValue="NULL"/>
      </ScalarOperator>
      </Then>
    <Else>
      <ScalarOperator>
        <Identifier>
          <ColumnReference Column="Expr1036"/>
        </Identifier>
      </ScalarOperator>
    </Else>
  </IF>
</ScalarOperator>

এক্সএমএল পরিকল্পনাটি ব্যবহার করে ISNULLএক্সপ্রেশন 2 হ'ল NULL:

SELECT * FROM theFunction ('2013-06-01', NULL)
<ScalarOperator ScalarString="CASE WHEN [Expr1035]=(0) THEN NULL ELSE [Expr1036] END">
  <IF>
    <Condition>
      <ScalarOperator>
        <Compare CompareOp="EQ">
          <ScalarOperator>
            <Identifier>
              <ColumnReference Column="Expr1035"/>
            </Identifier>
          </ScalarOperator>
          <ScalarOperator>
            <Const ConstValue="(0)"/>
          </ScalarOperator>
        </Compare>
      </ScalarOperator>
    </Condition>
    <Then>
      <ScalarOperator>
        <Const ConstValue="NULL"/>
      </ScalarOperator>
    </Then>
    <Else>
      <ScalarOperator>
        <Identifier>
          <ColumnReference Column="Expr1036"/>
        </Identifier>
      </ScalarOperator>
    </Else>
  </IF>
</ScalarOperator>

এক্সএমএল প্ল্যান ব্যবহার করে ISNULLএক্সপ্রেশন 2 একটি তারিখ:

SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
<ScalarOperator ScalarString="CASE WHEN [Expr1035]=(0) THEN NULL ELSE [Expr1036] END">
  <IF>
    <Condition>
      <ScalarOperator>
        <Compare CompareOp="EQ">
          <ScalarOperator>
            <Identifier>
              <ColumnReference Column="Expr1035"/>
            </Identifier>
          </ScalarOperator>
          <ScalarOperator>
            <Const ConstValue="(0)"/>
          </ScalarOperator>
        </Compare>
      </ScalarOperator>
    </Condition>
    <Then>
      <ScalarOperator>
        <Const ConstValue="NULL"/>
      </ScalarOperator>
    </Then>
    <Else>
      <ScalarOperator>
        <Identifier>
          <ColumnReference Column="Expr1036"/>
        </Identifier>
      </ScalarOperator>
    </Else>
  </IF>
</ScalarOperator>

তবে কেন এটি ঠিক কাজ করেছে তা ব্যাখ্যা করে না SELECT * FROM theFunction ('2013-06-01', '2013-06-01')। এক্সপ্রেশন ডেটাটাইপ এখনও একই। এবং উভয় পরামিতি dateযাইহোক ডেটাটাইপ হয়। আপনি কি কার্যকর করতে পারেন পরিকল্পনা?
মার্টিন স্মিথ

@ মার্টিনস্মিথ ক্যোয়ারির জন্য এখানে পরিকল্পনা রয়েছে যা ফলাফল দেয়। দ্বিতীয় প্রকাশটি যখন হয় তখন আমার কোনও পরিকল্পনা নেই NULL
কেরমিট

এর ভিতরে প্রকাশের কাস্টিংয়ের CASEকোনও প্রভাব ছিল না, ক্যোরি এখনও স্থগিত।
কেরমিট

2
দ্বিতীয় মামলার কোনও পরিকল্পনা কীভাবে আসে? এটি কি কারণ কোয়েরিটি শেষ হয় না? যদি তা হয় তবে আপনি কি আনুমানিক পরিকল্পনা পেতে পারেন? ভাবছেন যে বিভিন্ন অভিব্যক্তি কার্ডিনালিটির অনুমানগুলিকে পরিবর্তন করে এবং আপনি একটি আলাদা পরিকল্পনা নিয়ে এসেছেন।
মার্টিন স্মিথ

3
ISNULLএটা পছন্দ পরিকল্পনা সৌন্দর্য ভাল সহজসাধ্য। কলেজজিস্টে এটির একটি সাধারণ সমতার শিকারী রয়েছে [Date]='2013-06-01'যেখানে অন্যটির CASEএকটিতে ভবিষ্যদ্বাণী রয়েছে [Date]>='2013-06-01' AND [Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END AND PROBE([Bitmap1067],[Date])। আনুমানিক সারি যে আসছে আউট যোগদানের জন্য 28.393 হয় ISNULLসংস্করণ কিন্তু অনেক সময়ে কম 79.8জন্য CASEসংস্করণ প্রভাব পরিকল্পনা পরবর্তী পছন্দ যোগদান করুন। কেন এই ধরনের বৈষম্য হবে তা নিশ্চিত নয়।
মার্টিন স্মিথ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.