لماذا يفرض متغير الجدول فحص الفهرس بينما يستخدم الجدول المؤقت البحث عن الإشارات المرجعية؟

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

سؤال

أحاول أن أفهم سبب منع استخدام متغير الجدول للمُحسِّن من استخدام البحث عن الفهرس ثم البحث عن الإشارات المرجعية مقابل فحص الفهرس.

ملء الجدول:

CREATE TABLE dbo.Test 
(
    RowKey INT NOT NULL PRIMARY KEY, 
    SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
    ForeignKey INT NOT NULL 
) 

INSERT dbo.Test 
(
    RowKey, 
    ForeignKey
) 
SELECT TOP 1000000 
    ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
    ABS(CHECKSUM(NEWID()) % 10)     
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2 

CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey) 

قم بملء متغير جدول بسجل واحد وحاول البحث عن المفتاح الأساسي والعمود الثاني من خلال البحث في عمود المفتاح الخارجي:

DECLARE @Keys TABLE (RowKey INT NOT NULL) 

INSERT @Keys (RowKey) VALUES (10)

SELECT 
    t.RowKey,
    t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    @Keys k
ON
    t.ForeignKey = k.RowKey

وفيما يلي خطة التنفيذ:

enter image description here

الآن نفس الاستعلام باستخدام جدول مؤقت بدلاً من ذلك:

CREATE TABLE #Keys (RowKey INT NOT NULL) 

INSERT #Keys (RowKey) VALUES (10) 

SELECT 
    t.RowKey,
    t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    #Keys k
ON
    t.ForeignKey = k.RowKey

تستخدم خطة الاستعلام هذه البحث عن البحث والإشارة المرجعية:

enter image description here

لماذا يرغب المحسن في إجراء بحث عن الإشارة المرجعية باستخدام الجدول المؤقت، وليس متغير الجدول؟

يتم استخدام متغير الجدول في هذا المثال لتمثيل البيانات الواردة من خلال نوع جدول محدد من قبل المستخدم في إجراء مخزن.

أدرك أن البحث عن الفهرس قد لا يكون مناسبًا إذا حدثت قيمة المفتاح الخارجي مئات الآلاف من المرات.في هذه الحالة، من المحتمل أن يكون الفحص خيارًا أفضل.بالنسبة للسيناريو الذي قمت بإنشائه، لم يكن هناك صف بقيمة 10.ما زلت أعتقد أن هذا السلوك مثير للاهتمام وأرغب في معرفة ما إذا كان هناك سبب لذلك.

SQL كمان

إضافة OPTION (RECOMPILE) لم يغير السلوك.يحتوي UDDT على مفتاح أساسي.

@@VERSION هو SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (النسخة 7601:حزمة الخدمة 1) (المشرف)

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

المحلول

سبب هذا السلوك هو أن SQL Server لا يمكنه تحديد عدد الصفوف التي ستتطابق مع ExternalKey، نظرًا لعدم وجود فهرس به RowKey كعمود بادئ (يمكن استنتاج ذلك من الإحصائيات الموجودة في جدول #temp، ولكن لا يوجد ذلك موجودة لمتغيرات الجدول/UDTTs)، لذا فهي تقدر 100000 صف، وهو ما يتم التعامل معه بشكل أفضل من خلال المسح بدلاً من البحث+البحث.بحلول الوقت الذي يدرك فيه SQL Server أن هناك صفًا واحدًا فقط، يكون الوقت قد فات.

قد تتمكن من إنشاء UDTT الخاص بك بشكل مختلف؛في الإصدارات الأحدث من SQL Server، يمكنك إنشاء فهارس ثانوية على متغيرات الجدول، ولكن بناء الجملة هذا غير متوفر في 2008 R2.

راجع للشغل يمكنك الحصول على سلوك البحث (على الأقل في تجاربي المحدودة) إذا حاولت تجنب الصورة النقطية/المسبار عن طريق التلميح إلى حلقة متداخلة:

DECLARE @Keys TABLE (RowKey INT PRIMARY KEY); -- can't hurt

INSERT @Keys (RowKey) VALUES (10);

SELECT 
     t.RowKey
    ,t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    @Keys k
ON
    t.ForeignKey = k.RowKey
    OPTION (LOOP JOIN);

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

بالنسبة للاستعلامات الأكثر تعقيدًا، وعند الانتقال إلى SQL Server 2012 أو إصدار أحدث، فمن الممكن أن يكون ذلك علامة التتبع 2453 يمكن ان تساعد.ومع ذلك، لم يساعد هذا العلم في هذا الانضمام البسيط.وسيتم تطبيق نفس إخلاء المسؤولية - هذا مجرد شيء بديل لا ينبغي عليك فعله بشكل عام دون وجود الكثير من الوثائق وإجراءات اختبار الانحدار الصارمة.

كما أن حزمة الخدمة Service Pack 1 لم تعد مدعومة منذ فترة طويلة، لذا ينبغي عليك الاستمرار حزمة الخدمات 3 + MS15-058.

نصائح أخرى

يتم التعامل مع متغيرات الجدول والجداول المؤقتة بشكل مختلف بعدة طرق.هناك إجابة عظيمة هنا مع الكثير من التفاصيل حول مكان اختلافها.

على وجه التحديد في حالتك، أعتقد أن حقيقة أن الجداول المؤقتة يمكن أن تحتوي على إحصائيات إضافية تم إنشاؤها وخطط متوازية بينما تحتوي متغيرات الجدول على إحصائيات أكثر محدودية (لا توجد إحصائيات على مستوى العمود) ولا توجد خطط متوازية هي السبب.

قد يكون من الأفضل لك تفريغ متغير الجدول في جدول مؤقت طوال مدة الإجراء المخزن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى dba.stackexchange
scroll top