لماذا تستخدم هذه الاستعلامات المتشابهة مراحل تحسين مختلفة (معالجة المعاملات مقابل الخطة السريعة)؟

dba.stackexchange https://dba.stackexchange.com/questions/114853

سؤال

رمز المثال في عنصر الاتصال هذا

يظهر الخلل حيث

SELECT COUNT(*)
FROM   dbo.my_splitter_1('2') L1
       INNER JOIN dbo.my_splitter_1('') L2
         ON L1.csv_item = L2.csv_item

إرجاع النتائج الصحيحة.لكن ما يلي يعرض نتائج غير صحيحة (في عام 2014 باستخدام مقدر الكارديناليتي الجديد)

SELECT
    (SELECT COUNT(*)
    FROM dbo.my_splitter_1('2') L1
     INNER JOIN dbo.my_splitter_1('') L2
        ON L1.csv_item = L2.csv_item)

لأنه يقوم بتحميل نتائج L2 بشكل غير صحيح في التخزين المؤقت للتعبير الفرعي المشترك ثم يعيد عرض نتيجة ذلك لنتيجة L1.

كنت أشعر بالفضول لمعرفة سبب الاختلاف في السلوك بين الاستعلامين.يوضح Trace Flag 8675 أن الشخص الذي يعمل يدخل search(0) - transaction processing والذي فشل يدخل search(1) - quick plan.

لذلك أفترض أن توفر قواعد تحويل إضافية هو السبب وراء الاختلاف في السلوك (تعطيل إما BuildGbApply أو GenGbApplySimple يبدو لإصلاحه على سبيل المثال).

ولكن لماذا تواجه الخطتان لهذه الاستعلامات المتشابهة مراحل تحسين مختلفة؟مما قرأت search (0) يتطلب ثلاثة جداول على الأقل، وبالتأكيد لم يتم استيفاء هذا الشرط في المثال الأول.

هل كانت مفيدة؟

المحلول

كل مرحلة لها شروط الدخول.يعد "وجود ثلاثة مراجع للجدول على الأقل" أحد شروط الدخول التي نتحدث عنها عند إعطاء أمثلة بسيطة، ولكنها ليست الشرط الوحيد.

بشكل عام، يُسمح فقط للصلات والاتحادات الأساسية بالدخول للبحث 0؛الاستعلامات الفرعية العددية وشبه الصلات وما إلى ذلك.منع الدخول للبحث 0.هذه المرحلة مخصصة حقًا لأشكال الاستعلام من نوع OLTP الشائعة جدًا.لم يتم تمكين القواعد اللازمة لاستكشاف الأشياء الأقل شيوعًا.يحتوي استعلام المثال الخاص بك على استعلام فرعي عددي، لذا يفشل في الإدخال.

يعتمد ذلك أيضًا على كيفية حساب مراجع الجدول.لم يسبق لي أن بحثت بعمق في هذا الأمر مع الوظائف، ولكن من الممكن أن يكون المنطق هو حساب وظائف الجدول ذات القيمة بالإضافة إلى متغيرات الجدول التي تنتجها.من الممكن أيضًا حساب مرجع الجدول داخل الوظيفة نفسها - لست متأكدًا؛على الرغم من أنني أعلم أن الوظائف هي مجرد عمل شاق من جميع النواحي.

الخلل مع GenGbApplySimple قبيح.كان شكل الخطة هذا دائمًا ممكنًا، ولكن تم رفضه لأسباب تتعلق بالتكلفة حتى جاء التغيير إلى 100 صف مفترضًا للقيمة الأساسية المتغيرة للجدول.من الممكن فرض شكل الخطة الإشكالية على ما قبل عام 2014 م باستخدام أ USE PLAN تلميح، على سبيل المثال.

أنت على حق بشأن عنصر اتصال جديد كونها نفس القضية ذكرت سابقا.

لتقديم مثال، الاستعلام التالي مؤهل للبحث 0:

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY U.c1) 
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;

إن إجراء تغيير بسيط لتضمين استعلام فرعي عددي يعني الانتقال مباشرة إلى البحث 1:

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -- Changed!
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى dba.stackexchange
scroll top