it-swarm.asia

SQL اختر تنفيذ الكثير من الوقت

إنه تحديد بسيط من جدول مؤقت ، ويتم تركه لينضم إلى جدول موجود على مفتاحه الأساسي ، مع تحديدين فرعيين باستخدام أعلى 1 يشير إلى الجدول المرتبط.

في الكود:

SELECT
    TempTable.Col1,
    TempTable.Col2,
    TempTable.Col3,
    JoinedTable.Col1,
    JoinedTable.Col2,
    (
        SELECT TOP 1
            ThirdTable.Col1 -- Which is ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn1,
    (
        SELECT TOP 1
            ThirdTable.Col1 -- Which is also ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn2,
FROM
    #TempTable as TempTable
LEFT JOIN
    JoinedTable
ON (TempTable.PKColumn1 = JoinedTable.PKColumn1 AND 
    TempTable.PKColumn2 = JoinedTable.PKColumn2)
WHERE
    JoinedTable.WhereColumn IN  (1, 3)

هذه نسخة طبق الأصل من الاستعلام الخاص بي.

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

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

بدون هؤلاء TOP 1 تقوم بإرجاع أكثر من نتيجة وتثير خطأ.

المساعدة ، أي شخص؟

تحرير :

لذا أخبرتني خطة التنفيذ أنني افتقدت مؤشر. لقد قمت بإنشائه ، وقمت بإعادة إنشاء بعض الفهارس الأخرى. بعد فترة ، كانت خطة التنفيذ تستخدمهم ، ويعمل الاستعلام الآن بسرعة. المشكلة الوحيدة هي أنني لن أنجح في القيام بذلك مرة أخرى على خادم آخر ، لنفس الاستعلام. لذلك سيكون الحل هو HINT أي فهرس يستخدمه SQL Server.

9
Smur

أعتقد أنه في استعلام المليون تسجيل ، عليك تجنب أشياء مثل OUTER JOINS. أقترح استخدام UNION ALL بدلاً من LEFT JOIN. طالما أعتقد أن CROSS APPLY أكثر كفاءة من الاستعلام الفرعي في بند التحديد ، فسأعدل الاستعلام الذي كتبه كونارد فريكس ، والذي أعتقد أنه صحيح.

الآن: عندما بدأت في تعديل الاستعلام الخاص بك لاحظت أن لديك جملة WHERE تقول: JoinedTable.WhereColumn IN (1, 3). في هذه الحالة ، إذا كان الحقل خاليًا ، ستصبح الحالة خاطئة. ثم لماذا تستخدم LEFT JOIN أثناء تصفية الصفوف ذات القيم الخالية؟ فقط استبدل LEFT JOIN باستخدام INNER JOIN ، أضمن أنه سيصبح أسرع.

حول INDEX:

يرجى ملاحظة أنه عندما يكون لديك فهرس على طاولة ، قل

table1(a int, b nvarchar)

والفهرس الخاص بك هو:

nonclustered index ix1 on table1(a)

وتريد القيام بشيء مثل هذا:

select a,b from table1
where a < 10

في الفهرس الخاص بك لم تقم بتضمين العمود b فماذا يحدث؟

إذا كان خادم SQL يستخدم الفهرس الخاص بك ، فسيتعين عليه البحث في الفهرس المسمى "Index Seek" ثم الرجوع إلى الجدول الرئيسي للحصول على العمود b ، المسمى "بحث". قد يستغرق هذا الإجراء وقتًا أطول بكثير من مسح الجدول نفسه: "Table Scan".

ولكن استنادًا إلى الإحصائيات التي يمتلكها خادم SQL ، في مثل هذه المواقف ، قد لا يستخدم فهرسك على الإطلاق.

لذا أولاً ، تحقق من Execution Plan لمعرفة ما إذا كان الفهرس مستخدمًا على الإطلاق.

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

nonclustered index ix1 on table1(a) include(b)

في هذه الحالة ، لن تكون هناك حاجة إلى Look Up ، وسيتم تنفيذ استعلامك بشكل أسرع.

7
Maziar Taheri

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

استخدام الصلات اليسرى إلى مثيلين من الجدول الثالث

SELECT
  TempTable.Col1,
  TempTable.Col2,
  TempTable.Col3,
  JoinedTable.Col1,
  JoinedTable.Col2,
  ThirdTable.Col1 AS ThirdTableColumn1,
  ThirdTable2.Col1 AS ThirdTableColumn2
FROM #TempTable as TempTable
LEFT JOIN JoinedTable ON (TempTable.PKColumn1 = JoinedTable.PKColumn2 AND 
    TempTable.PKColumn 2 = JoinedTable.PKColumn2)
LEFT JOIN ThirdTable ON ThirdTable.SomeColumn = JoinedTable.SomeColumn
LEFT JOIN ThirdTable ThirdTable2 ON ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
WHERE
    JoinedTable.WhereColumn IN  (1, 3)

باستخدام جدول مشتق

 SELECT 
      TempTable.Col1,
      TempTable.Col2,
      TempTable.Col3,
      DerivedTable.Col1,
      DerivedTable.Col2,
      DerivedTable.ThirdTableColumn1,
      DerivedTable.ThirdTableColumn2
 FROM #TempTable as TempTable
    LEFT JOIN (SELECT
                 JoinedTable.PKColumn2,
                 JoinedTable.Col1,
                 JoinedTable.Col2,
                 JoinedTable.WhereColumn,
                 ThirdTable.Col1 AS ThirdTableColumn1,
                 ThirdTable2.Col1 AS ThirdTableColumn2
               FROM JoinedTable
               LEFT JOIN ThirdTable ON ThirdTable.SomeColumn = JoinedTable.SomeColumn
               LEFT JOIN ThirdTable ThirdTable2 ON ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn) 
        DerivedTable ON (TempTable.PKColumn1 = DerivedTable .PKColumn2 AND 
        TempTable.PKColumn2 = DerivedTable.PKColumn2)
    WHERE
        DerivedTable.WhereColumn IN  (1, 3)
6
John Hartsock

حاول تطبيق الصليب بدلاً من ذلك

SELECT
    TempTable.Col1,
    TempTable.Col2,
    TempTable.Col3,
    JoinedTable.Col1,
    JoinedTable.Col2,
    ThirdTableColumn1.col1,
    ThirdTableColumn2.col1

FROM
    #TempTable as TempTable
LEFT JOIN
    JoinedTable
ON (TempTable.PKColumn1 = JoinedTable.PKColumn2 AND 
    TempTable.PKColumn 2 = JoinedTablePKColumn2)

CROSS APPLY
(
        SELECT TOP 1
            ThirdTable.Col1 -- Which is ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn1
CROSS APPLY    (
        SELECT TOP 1
            ThirdTable.Col1 -- Which is also ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn2,
WHERE
    JoinedTable.WhereColumn IN  (1, 3)

يمكنك أيضًا استخدام CTE و row_number أو استعلام مضمّن باستخدام MIN

2
Conrad Frix

انقل بتات JOIN خارج الجزء الرئيسي من الفقرة وضعها كاختيار فرعي. يضمن نقلها إلى قسم WHERE و JOIN عدم الحاجة إلى تحديد TOP 1 مرارًا وتكرارًا ، وهو ما أعتقد أنه سبب بطء hte. إذا كنت تريد التحقق من ذلك ، فافحص خطة التنفيذ.

2
Gregory A Beamer

تحتاج المراجع ThirdTable ، (التحديدات الفرعية في المثال الخاص بك) إلى نفس انتباه الفهرس مثل أي جزء آخر من الاستعلام.

بغض النظر عما إذا كنت تستخدم اختيارات فرعية:

(
    SELECT TOP 1
        ThirdTable.Col1 -- Which is ThirdTable's Primary Key
    FROM
        ThirdTable
    WHERE
        ThirdTable.SomeColumn = JoinedTable.SomeColumn
) as ThirdTableColumn1,
(
    SELECT TOP 1
        ThirdTable.Col1 -- Which is also ThirdTable's Primary Key
    FROM
        ThirdTable
    WHERE
        ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
) as ThirdTableColumn2,

ينضم إلى اليسار (كما اقترح جون هارتسوك):

LEFT JOIN ThirdTable ON ThirdTable.SomeColumn = JoinedTable.SomeColumn
LEFT JOIN ThirdTable ThirdTable2 ON ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn

تطبيق CROSS (كما اقترح كونراد فريكس):

CROSS APPLY
(
        SELECT TOP 1
            ThirdTable.Col1 -- Which is ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn1
CROSS APPLY    (
        SELECT TOP 1
            ThirdTable.Col1 -- Which is also ThirdTable's Primary Key
        FROM
            ThirdTable
        WHERE
            ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
    ) as ThirdTableColumn2

تحتاج إلى ضمان covering indexes معرّفة لـ ThirdTable.SomeColumn و ThirdTable.SomeOtherColumn والفهارس فريدة. وهذا يعني أنك ستحتاج إلى مزيد من تأهيل مراجع ThirdTable للتخلص من تحديد صفوف متعددة وتحسين الأداء. خيار sub selects ، LEFT JOIN ، أو CROSS APPLY لن يهم حقًا حتى تحسن الانتقائية لـ ThirdTable.SomeColumn و ThirdTable.SomeOtherColumn بتضمين المزيد من الأعمدة لضمان الانتقائية الفريدة. حتى ذلك الحين ، أتوقع أن يستمر أداؤك في المعاناة.

ال covering index تم تقديم الموضوع بشكل جيد بواسطة Maziar Taheri ؛ بينما لا أكرر عمله ، أؤكد على الحاجة إلى استخدام فهارس التغطية.

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

2
Robert Miller