কেন একটি subquery সারি অনুমান 1 এ হ্রাস করে?


26

নিম্নলিখিত কনট্রিভড তবে সাধারণ ক্যোয়ারী বিবেচনা করুন:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE_2) 
  END AS ID2
FROM X_HEAP;

আমি এই প্রশ্নের জন্য চূড়ান্ত সারি অনুমানটি X_HEAPটেবিলের সারি সংখ্যার সমান হবে বলে আশা করব । আমি সাবকিউরিতে যা কিছু করছি তা সারি অনুমানের জন্য গুরুত্বপূর্ণ নয় কারণ এটি কোনও সারি ফিল্টার করতে পারে না। যাইহোক, এসকিউএল সার্ভার ২০১ 2016-তে আমি দেখি যে সারি অনুমানটি সাবকিউরিটির কারণে হ্রাস পেয়েছে:

খারাপ জিজ্ঞাসা

কেন এমন হয়? আমি এটি সম্পর্কে কি করতে পারি?

ডান সিনট্যাক্স সহ এই সমস্যাটি পুনরুত্পাদন করা খুব সহজ। এখানে টেবিল সংজ্ঞাগুলির একটি সেট রয়েছে যা এটি করবে:

CREATE TABLE dbo.X_HEAP (ID INT NOT NULL)
CREATE TABLE dbo.X_OTHER_TABLE (ID INT NOT NULL);
CREATE TABLE dbo.X_OTHER_TABLE_2 (ID INT NOT NULL);

INSERT INTO dbo.X_HEAP WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;

CREATE STATISTICS X_HEAP__ID ON X_HEAP (ID) WITH FULLSCAN;

ডিবি ফিডাল লিঙ্ক

উত্তর:


22

এই কার্ডিনালিটি অনুমান (সিই) প্রকাশিত হয় যখন:

  1. যোগদানটি হ'ল একটি বহির্মুখী যোগ যা একটি পাস- থ্রো প্রিকিকেট সহ
  2. নির্বাচনশীলতা পাস-থ্রু সম্পৃক্ত হতে অনুমান করা হয় ঠিক 1

দ্রষ্টব্য: সিলিটিভিটি নির্ধারণ করতে ব্যবহৃত বিশেষ ক্যালকুলেটরটি গুরুত্বপূর্ণ নয়।


বিস্তারিত

সিই সমষ্টি হিসাবে বাহ্যিক জোনের সিলেকটিভিটি গণনা করে :

  • ভেতরের যোগদানের একই সম্পৃক্ত সঙ্গে নির্বাচনশীলতা
  • বিরোধী যোগদানের একই সম্পৃক্ত সঙ্গে নির্বাচনশীলতা

বাহ্যিক এবং অভ্যন্তরীণ যোগদানের মধ্যে কেবলমাত্র পার্থক্যটি হ'ল বাহ্যিক জোড় সারিগুলিও প্রত্যাবর্তন করে যা জোড় প্রাকটিকের সাথে মেলে না। এন্টি জয়েন ঠিক এই পার্থক্য সরবরাহ করে। সরাসরি বাইরের যোগদানের চেয়ে অভ্যন্তরীণ এবং বিরোধী যোগদানের জন্য কার্ডিনালিটির অনুমান সহজ।

যোগদানের নির্বাচনের অনুমান প্রক্রিয়াটি খুব সোজা:

  • প্রথমত, পাস-থ্রিডিকেটের সিলেকটিভিটি মূল্যায়ন করা হয়। SPT
    • এটি পরিস্থিতিতে যে কোনও ক্যালকুলেটর ব্যবহার করে করা হয়।
    • শিকারী হ'ল সম্পূর্ণ বিষয়, কোনও অবহেলা IsFalseOrNullউপাদান সহ component
  • অভ্যন্তরীণ যোগদান নির্বাচন: 1 - SPT
  • বিরোধী যোগদানের নির্বাচন: SPT

এন্টি জয়েনটি সারিগুলিকে প্রতিনিধিত্ব করে যা জোড়কে 'মধ্য দিয়ে যাবে'। অভ্যন্তরীণ জোড় সারিগুলি উপস্থাপন করে যা 'মধ্য দিয়ে যাবে না'। নোট করুন যে 'পাস দিয়ে' এর অর্থ সারিগুলি যা অভ্যন্তরীণ দিকটি মোটেও চালনা ছাড়াই জোড়ের মধ্য দিয়ে প্রবাহিত হয়। জোর দেওয়ার জন্য: সমস্ত সারি যোগদানের মাধ্যমে ফিরে আসবে, পার্থক্যটি সারিগুলির মধ্যে যেগুলি উদীয়মানের আগে জোড়ার অভ্যন্তরীণ দিকটি চালায় এবং যেগুলি না করে between

স্পষ্টতই, যোগ করার সাথে সর্বদা 1 টির একটি সম্পূর্ণ নির্বাচন দেওয়া উচিত, অর্থাত সমস্ত সারি জোড় দ্বারা প্রত্যাবর্তিত হিসাবে ফিরে আসবে।1 - SPTSPT

প্রকৃতপক্ষে, উপরের গণনাটি 1 ব্যতীত সমস্ত মানের জন্য বর্ণিত ঠিক মতো কাজ করে ।SPT

যখন = 1, উভয় অভ্যন্তরীণ যোগদান এবং বিরোধী জোড় নির্বাচনগুলি শূন্য বলে অনুমান করা হয় যার ফলস্বরূপ এক সারিটির একটি কার্ডিনালিটি অনুমান (সামগ্রিকভাবে যোগদানের জন্য) হয়। আমি যতদূর বলতে পারি এটি অনিচ্ছাকৃত এবং এটি একটি বাগ হিসাবে রিপোর্ট করা উচিত।SPT


একটি সম্পর্কিত সমস্যা

পৃথক সিই সীমাবদ্ধতার কারণে এই ত্রুটিটি কারও ভাবার চেয়ে বেশি প্রকাশিত হওয়ার সম্ভাবনা রয়েছে। এটি তখন উদ্ভূত হয় যখন CASEঅভিব্যক্তিটি একটি EXISTSধারা ব্যবহার করে (সাধারণ হিসাবে)। উদাহরণস্বরূপ, প্রশ্ন থেকে নিম্নলিখিত পরিবর্তিত ক্যোয়ারী অপ্রত্যাশিত কার্ডিনালিটির অনুমানের মুখোমুখি হয় না :

-- This is fine
SELECT 
    CASE
        WHEN XH.ID = 1
        THEN (SELECT TOP (1) XOT.ID FROM dbo.X_OTHER_TABLE AS XOT) 
    END
FROM dbo.X_HEAP AS XH;

একটি তুচ্ছ পরিচয় করিয়ে EXISTSদেওয়ার কারণে সমস্যাটি উত্থিত হয়:

-- This is not fine
SELECT 
    CASE
        WHEN EXISTS (SELECT 1 WHERE XH.ID = 1)
        THEN (SELECT TOP (1) XOT.ID FROM dbo.X_OTHER_TABLE AS XOT) 
    END
FROM dbo.X_HEAP AS XH;

ব্যবহার EXISTSসঞ্চালনের পরিকল্পনা প্রবর্তন একটি আধা যোগদান (হাইলাইট করা):

আধা যোগদান পরিকল্পনা

আধা যোগদানের জন্য অনুমানটি ঠিক আছে। সমস্যাটি হ'ল সিই সম্পর্কিত তদন্ত কলামটিকে একটি সাধারণ অভিক্ষেপ হিসাবে বিবেচনা করে, 1 এর একটি নির্দিষ্ট নির্বাচনের সাথে:

Semijoin with probe column treated as a Project.

Selectivity of probe column = 1

EXISTSদফার বিষয়বস্তু নির্বিশেষে এটি সিই ইস্যুতে প্রকাশের জন্য প্রয়োজনীয় শর্তগুলির একটিতে এটি স্বয়ংক্রিয়ভাবে পূরণ করে ।


গুরুত্বপূর্ণ পটভূমি তথ্যের জন্য, ক্রেগ ফ্রিডম্যান দ্বারা এক্সপ্রেশনগুলিতে সাবকিউরিসCASE দেখুন ।


22

এটি অবশ্যই অনিচ্ছাকৃত আচরণের মতো বলে মনে হচ্ছে। এটি সত্য যে কোনও পরিকল্পনার প্রতিটি ধাপে কার্ডিনালিটি অনুমানের প্রয়োজন হয় না তবে এটি একটি তুলনামূলকভাবে সহজ ক্যোয়ারী পরিকল্পনা এবং চূড়ান্ত কার্ডিনালিটি অনুমান কোয়েরিটি যা করছে তার সাথে সামঞ্জস্যপূর্ণ নয়। এত কম কার্ডিনালিটির অনুমানের ফলে আরও জটিল পরিকল্পনায় জোয়ারের ধরণের পছন্দগুলি এবং অন্যান্য টেবিলের জন্য প্রবাহের অ্যাক্সেসের পদ্ধতিগুলি খারাপ ফলাফল হতে পারে।

পরীক্ষার এবং ত্রুটির মাধ্যমে আমরা কয়েকটি অনুরূপ ক্যোয়ারী নিয়ে আসতে পারি যার জন্য সমস্যাটি উপস্থিত হয় না:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT -1) 
  END AS ID2
FROM dbo.X_HEAP;

SELECT 
  ID
, CASE
    WHEN ID < 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    WHEN ID >= 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
  END AS ID2
FROM dbo.X_HEAP;

আমরা আরও প্রশ্নের সাথে আসতে পারি যার জন্য সমস্যাটি উপস্থিত হয়:

SELECT 
  ID
, CASE
    WHEN ID < 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    WHEN ID >= 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
  END AS ID2
FROM dbo.X_HEAP;

SELECT 
  ID
, CASE
    WHEN ID = 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT -1) 
  END AS ID2
FROM dbo.X_HEAP;

SELECT 
  ID
, CASE
    WHEN ID = 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
  END AS ID2
FROM dbo.X_HEAP;

এখানে একটি প্যাটার্ন উপস্থিত রয়েছে: যদি এর মধ্যে এমন কোনও ভাব থাকে CASEযা কার্যকর হয় বলে আশা করা হয় না এবং ফলাফল প্রকাশটি কোনও টেবিলের বিপরীতে সাবকোয়ারি হয় তবে সারি অনুমানটি সেই অভিব্যক্তির পরে 1 এ চলে যায়।

যদি আমি একটি ক্লাস্টার ইনডেক্স সহ কোনও টেবিলের বিপরীতে কোয়েরিটি লিখি তবে নিয়মগুলি কিছুটা পরিবর্তন। আমরা একই তথ্য ব্যবহার করতে পারি:

CREATE TABLE dbo.X_CI (ID INT NOT NULL, PRIMARY KEY (ID))

INSERT INTO dbo.X_CI WITH (TABLOCK)
SELECT * FROM dbo.X_HEAP;

UPDATE STATISTICS X_CI WITH FULLSCAN;

এই ক্যোয়ারিতে একটি 1000 সারির চূড়ান্ত অনুমান রয়েছে:

SELECT 
  ID
, CASE
    WHEN ID = 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
    ELSE (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
  END
FROM dbo.X_CI;

তবে এই ক্যোয়ারিতে একটি 1 সারির চূড়ান্ত অনুমান রয়েছে:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
  END
FROM dbo.X_CI;

এটি আরও খনন করার জন্য আমরা ক্যোরি অপ্টিমাইজার কীভাবে নির্বাচনের গণনা সম্পাদন করেছে সে সম্পর্কে তথ্য পেতে অননুমোদিত ট্রেস ফ্ল্যাগ 2363 ব্যবহার করতে পারি । আমি অনাকাঙ্ক্ষিত ট্রেস পতাকা 8606 এর সাথে ট্রেস পতাকাটি জোড়া লাগানো সহায়ক বলে মনে করেছি । টিএফ 23৩৩ প্রকল্পটি সাধারণীকরণের পরে সরলীকৃত গাছ এবং গাছ উভয়ের জন্য বেছে বেছে গণনা দিয়েছে বলে মনে হচ্ছে। উভয় ট্রেস পতাকা সক্ষম করা তা পরিষ্কার করে দেয় কোন গাছে কোন গণনা প্রযোজ্য।

আসুন প্রশ্নে পোস্ট করা মূল প্রশ্নের জন্য এটি চেষ্টা করে দেখুন:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE_2) 
  END AS ID2
FROM X_HEAP
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

এখানে আউটপুট অংশের কিছু অংশ যা আমি মনে করি কিছু মন্তব্যের সাথে প্রাসঙ্গিক:

Plan for computation:

  CSelCalcColumnInInterval -- this is the type of calculator used

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID -- this is the column used for the calculation

Pass-through selectivity: 0 -- all rows are expected to have a true value for the case expression

Stats collection generated: 

  CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter) -- the row estimate after the join will still be 1000

      CStCollBaseTable(ID=1, CARD=1000 TBL: X_HEAP)

      CStCollBaseTable(ID=2, CARD=1 TBL: X_OTHER_TABLE)

...

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 1 -- no rows are expected to have a true value for the case expression

Stats collection generated: 

  CStCollOuterJoin(ID=9, CARD=1 x_jtLeftOuter) -- the row estimate after the join will still be 1

      CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter) -- here is the row estimate after the previous join

          CStCollBaseTable(ID=1, CARD=1000 TBL: X_HEAP)

          CStCollBaseTable(ID=2, CARD=1 TBL: X_OTHER_TABLE)

      CStCollBaseTable(ID=3, CARD=1 TBL: X_OTHER_TABLE_2)

এখন আসুন এটির অনুরূপ ক্যোয়ারির জন্য এটি চেষ্টা করি যাতে সমস্যা নেই। আমি এটি ব্যবহার করতে যাচ্ছি:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT -1) 
  END AS ID2
FROM dbo.X_HEAP
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

একেবারে শেষে ডিবাগ আউটপুট:

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 1

Stats collection generated: 

  CStCollOuterJoin(ID=9, CARD=1000 x_jtLeftOuter)

      CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter)

          CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_HEAP)

          CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE)

      CStCollConstTable(ID=4, CARD=1) -- this is different than before because we select a constant instead of from a table

আসুন অন্য কোয়েরি চেষ্টা করুন যার জন্য খারাপ সারি অনুমানটি উপস্থিত রয়েছে:

SELECT 
  ID
, CASE
    WHEN ID < 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    WHEN ID >= 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
  END AS ID2
FROM dbo.X_HEAP
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

একেবারে শেষে কার্ডিনালিটির অনুমানটি 1 সারিতে নেমে আসে, আবার পাস-থ্রো সিলেকটিভিটি = 1 পরে আবার কার্ডিনালিটির অনুমান 0.501 এবং 0.499 এর নির্বাচনের পরে সংরক্ষণ করা হয়।

Plan for computation:

 CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 0.501

...

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 0.499

...

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 1

Stats collection generated: 

  CStCollOuterJoin(ID=12, CARD=1 x_jtLeftOuter) -- this is associated with the ELSE expression

      CStCollOuterJoin(ID=11, CARD=1000 x_jtLeftOuter)

          CStCollOuterJoin(ID=10, CARD=1000 x_jtLeftOuter)

              CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_HEAP)

              CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE)

          CStCollBaseTable(ID=3, CARD=1 TBL: dbo.X_OTHER_TABLE_2)

      CStCollBaseTable(ID=4, CARD=1 TBL: X_OTHER_TABLE)

আসুন আবার আর একটি একই ধরণের ক্যোয়ারিতে স্যুইচ করা যাক এতে সমস্যা নেই। আমি এটি ব্যবহার করতে যাচ্ছি:

SELECT 
  ID
, CASE
    WHEN ID < 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    WHEN ID >= 500 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
  END AS ID2
FROM dbo.X_HEAP
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

ডিবাগ আউটপুটে কখনওই কোনও পদক্ষেপ হয় না যার পাসের মধ্য দিয়ে 1 টি বেছে নেওয়া হয় The কার্ডিনালিটির অনুমান 1000 সারিতে থাকে।

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_HEAP].ID

Pass-through selectivity: 0.499

Stats collection generated: 

  CStCollOuterJoin(ID=9, CARD=1000 x_jtLeftOuter)

      CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter)

          CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_HEAP)

          CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE)

      CStCollBaseTable(ID=3, CARD=1 TBL: dbo.X_OTHER_TABLE_2)

End selectivity computation

যখন ক্লাস্টার ইনডেক্স সহ কোনও টেবিল জড়িত তখন ক্যোয়ারীর কী হবে? সারি প্রাক্কলন ইস্যু সহ নিম্নোক্ত প্রশ্নটি বিবেচনা করুন:

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
  END
FROM dbo.X_CI
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

ডিবাগ আউটপুটটির সমাপ্তি আমরা ইতিমধ্যে যা দেখেছি তার অনুরূপ:

Plan for computation:

  CSelCalcColumnInInterval

      Column: QCOL: [SE_DB].[dbo].[X_CI].ID

Pass-through selectivity: 1

Stats collection generated: 

  CStCollOuterJoin(ID=9, CARD=1 x_jtLeftOuter)

      CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter)

          CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_CI)

          CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE)

      CStCollBaseTable(ID=3, CARD=1 TBL: dbo.X_OTHER_TABLE_2)

তবে ইস্যু ছাড়াই সিআইয়ের বিরুদ্ধে অনুসন্ধানের আলাদা আউটপুট রয়েছে। এই ক্যোয়ারী ব্যবহার করে:

SELECT 
  ID
, CASE
    WHEN ID = 0 
    THEN (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE_2) 
    ELSE (SELECT TOP 1 ID FROM dbo.X_OTHER_TABLE) 
  END
FROM dbo.X_CI
OPTION (QUERYTRACEON 3604, QUERYTRACEON 2363, QUERYTRACEON 8606);

বিভিন্ন ক্যালকুলেটর ব্যবহার হচ্ছে ফলাফল Results CSelCalcColumnInIntervalআর প্রদর্শিত হবে না:

Plan for computation:

  CSelCalcFixedFilter (0.559)

Pass-through selectivity: 0.559

Stats collection generated: 

  CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter)

      CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_CI)

      CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE_2)

...

Plan for computation:

  CSelCalcUniqueKeyFilter

Pass-through selectivity: 0.001

Stats collection generated: 

  CStCollOuterJoin(ID=9, CARD=1000 x_jtLeftOuter)

      CStCollOuterJoin(ID=8, CARD=1000 x_jtLeftOuter)

          CStCollBaseTable(ID=1, CARD=1000 TBL: dbo.X_CI)

          CStCollBaseTable(ID=2, CARD=1 TBL: dbo.X_OTHER_TABLE_2)

      CStCollBaseTable(ID=3, CARD=1 TBL: dbo.X_OTHER_TABLE)

উপসংহারে, আমরা নিম্নলিখিত শর্তাবলী subquery পরে একটি খারাপ সারি অনুমান পেতে প্রদর্শিত হবে:

  1. CSelCalcColumnInIntervalনির্বাচনশীলতা ক্যালকুলেটর ব্যবহার করা হয়। কখন এটি ব্যবহার করা হয় তা আমি ঠিক জানি না তবে বেস টেবিলটি যখন একটি গাদা হয়ে থাকে তখন এটি প্রায়শই প্রদর্শিত হবে।

  2. পাস-থ্রো সিলেকটিভিটি = ১. অন্য কথায়, CASEএক্সপ্রেশনগুলির মধ্যে একটির সারিগুলির জন্য মিথ্যা হিসাবে মূল্যায়ন করা হবে বলে আশা করা হচ্ছে। প্রথম CASEঅভিব্যক্তিটি সমস্ত সারিটির জন্য সত্য বলে মূল্যায়ন করে তা বিবেচ্য নয়।

  3. এখানে একটি বাহ্যিক যোগদান রয়েছে CStCollBaseTable। অন্য কথায়, CASEফলাফলের প্রকাশটি একটি টেবিলের বিপরীতে subquery হয়। একটি ধ্রুবক মান কাজ করবে না।

সম্ভবত এই শর্তগুলির মধ্যে কোয়েরি অপ্টিমাইজারটি অনিচ্ছাকৃতভাবে নেস্টেড লুপের অভ্যন্তরীণ অংশে করা কাজের পরিবর্তে বাইরের টেবিলের সারি প্রাক্কলনে পাস-থ্রো সিলেকটিভিটি প্রয়োগ করছে। এটি সারি প্রাক্কলনটি 1 এ কমিয়ে আনবে।

আমি দুটি কাজের ক্ষেত্র সন্ধান করতে সক্ষম হয়েছি। APPLYসাবকিউয়ের পরিবর্তে ব্যবহার করার সময় আমি সমস্যাটি পুনরুত্পাদন করতে পারিনি। ট্রেস পতাকা 2363 এর আউটপুট এর সাথে খুব আলাদা ছিল APPLY। প্রশ্নের মূল প্রশ্নটি পুনরায় লেখার একটি উপায় এখানে:

SELECT 
  h.ID
, a.ID2
FROM X_HEAP h
OUTER APPLY
(
SELECT CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE_2) 
  END
) a(ID2);

ভাল জিজ্ঞাসা 1

উত্তরাধিকারসূত্রে সিই সমস্যাটি এড়িয়ে চলেছে।

SELECT 
  ID
, CASE
    WHEN ID <> 0 
    THEN (SELECT TOP 1 ID FROM X_OTHER_TABLE) 
    ELSE (SELECT TOP 1 ID FROM X_OTHER_TABLE_2) 
  END AS ID2
FROM X_HEAP
OPTION (USE HINT('FORCE_LEGACY_CARDINALITY_ESTIMATION'));

ভাল জিজ্ঞাসা 2

এই ইস্যুটির জন্য একটি সংযুক্ত আইটেম জমা দেওয়া হয়েছিল (পল হোয়াইট তার উত্তরে প্রদত্ত কিছু বিবরণ সহ)।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.