يعمل الاستعلام بشكل أبطأ عدة مرات عند مقارنة عمود BIT بالرقم 0 بدلاً من 1

StackOverflow https://stackoverflow.com/questions/468641

  •  19-08-2019
  •  | 
  •  

سؤال

أستخدم طريقة عرض تعتمد على استعلام معقد يحتوي على 17 صلة (داخلية وخارجية يسارًا/يمينًا) واستعلامات فرعية.يتم عرض جميع صفوف العرض في حوالي 5 ثوانٍ.

SELECT * FROM a_view;

يحتوي أحد أعمدة العرض على النوع BIT.وعندما أقوم بتصفية صفوف العرض ومقارنتها بالرقم 1، يعمل الاستعلام مرة أخرى لمدة 5 ثوانٍ تقريبًا.

SELECT * FROM a_view WHERE c = 1;

ولكن عندما أقارن عمود BIT هذا بـ 0، فإن الاستعلام يعمل لمدة 50 ثانية تقريبًا (أبطأ بـ 10 مرات).

SELECT * FROM a_view WHERE c = 0;

يعمل هذا الاستعلام الذي يُرجع نفس صفوف النتائج كما هو متوقع لمدة 10 ثوانٍ تقريبًا:

SELECT * FROM a_view 
EXCEPT
SELECT * FROM a_view WHERE c = 1;

لذا أتساءل لماذا تستغرق المقارنة مع 0 أو "FALSE" الكثير من الوقت؟أي أفكار، من فضلك.

يتم الفرز في حقل BIT هذا بسرعة.التصفية حسب الأعمدة الأخرى سريعة أيضًا.

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

المحلول

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

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

لمرجعية، كيو توقف تقييم جميع خطط محتملة بعد 12 ينضم افتراضيا. SQL Server سوف يكون حد مماثل على وجه اليقين. 17 ينضم سيستغرق (2 * 13) * (2 * 14) * (2 * 15) * (2 * 16) * (2 * 17) أضعاف طويلة لتقييم - إنها أكثر من كافية لتطغى على أي RDBMS التي لديها وجدت من أي وقت مضى، <م> أو في أي وقت سوف .

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

وماذا تحتاج للانضمام الى 17 الجداول؟ لا توجد وسيلة يمكنك تبسيط مخطط DB لديك؟

نصائح أخرى

وعلى مشغل SQL Server SQL يضع الاستعلام SQL كله من رأي داخل بيان SQL الذي كتب على عرض ثم يحاول ذلك على الوجه الأمثل.

وهذا يمكن أن يؤدي إلى الحالة التي يكون فيها مع ج = 0، فإن الإحصاءات من الجداول المستخدمة تبين أن هناك أكثر من ذلك بكثير صفوف مطابقة التي المسند من مع c = 1. على سبيل المثال، مع ج = 1، الجدول الذي يحتوي على الحقل ج وهو مركز ينضم قد يعود بعد 5 صفوف مطابقة، الأمر الذي يؤدي إلى خطة تنفيذ مختلفة تماما مما لو إرجاع الجدول 1 مليون صف (والذي هو على سبيل المثال الوضع بالنسبة للج = 0).

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

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

select * from subquery_x;

وسريع جدا، وانتهت في الأساس على الفور (عاد لتوه حوالي 500 الصفوف) كما يجب

select * from subquery_x where column_x = 1  

وdtto، سريع جدا، column_x هو عمود بت غير فارغة

select * from subquery_x where column_x = 0
select * from subquery_x where column_x != 1

ويجب أن تعود نحو 300 الصفوف، على حد سواء جدا، بطيئة جدا، في واقع الأمر استغرق عدة دقائق !!

<القوي> بسيط (ولكن غريب) حل - يمكنك تحويل عمود في مكان جملة لtinyint

select * from subquery_x where convert(tinyint,column_x) = 0

وأنا أعلم أن هذا قد يكون لها بعض الآثار الجانبية الأداء، لكنه يعمل مثل السحر، مقارنة قيمة العمود المحولة إلى 1 كان أيضا سريع جدا، لذلك اسمحوا لي من هذا القبيل (كان يستخدم في تقرير مع تقديم قيمة مقارنة كمعلمة)

إذا كان أي شخص يعرف لماذا يحدث هذا، اسمحوا لنا أن نعرف، وأظن انها علة، ولكن من يدري، قد يكون جيدا كما سمة سيئة: -)

مشابه ل horcic.romanالحل...لقد قمت بإلقاء القيمة أو العمود على BIT لزيادة كبيرة في السرعة.

myColumn = CAST(1 AS BIT)

CAST(myColumn AS BIT) = 1

من الواضح أنه غريب جدًا نظرًا لأن العمود ليس فارغًا بعض الشيء.

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