it-swarm.asia

ما هو الأكثر فعالية ، بند حيث أو صلة بملايين الجداول بالإضافة إلى الصف؟

نحن ندير موقعًا إلكترونيًا يحتوي على 250 مم من الصفوف في جدول واحد وفي جدول آخر ننضم إليه لمعظم الاستعلامات يحتوي على أقل من 15 مم من الصفوف.

هياكل العينة:

MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows

يتعين علينا بانتظام القيام ببعض الاستفسارات مقابل كل هذه الجداول. إحداها هو الحصول على إحصاءات للمستخدمين المجانيين (~ 10 آلاف مستخدم مجاني).

Select Count(1) from DetailsTable dt 
join MasterTable mt on mt.Id = dt.MasterId 
join UserTable ut on ut.Id = mt.UserId 
where ut.Role is null and mt.created between @date1 and @date2

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

في هذه الحالة سيكون من الحكمة استخدام أماكن بدلاً من الانضمام أو ربما where column in(...)؟

20
Jeremy Boyd

بالنسبة إلى قواعد إدارة قواعد البيانات (RDBMS) الحديثة ، لا يوجد فرق بين "JOIN صريحة" و "JOIN-in-the-WHERE" (إذا كانت جميع JOINS INNER) تتعلق بالأداء وخطة الاستعلام.

بناء جملة JOIN الصريح أكثر وضوحا وأقل غموضا (انظر الروابط أدناه)

الآن ، JOIN-before-WHERE هي معالجة منطقية معالجة فعلية معالجة والمتفائلون الحديثون أذكياء بما يكفي لتحقيق ذلك.

مشكلتك هنا هي على الأرجح الفهرسة.

يرجى إظهار جميع الفهارس والمفاتيح على هذه الجداول. وخطط الاستعلام

ملاحظة: كان هذا السؤال سيغلق على StackOverflow لكونه مكررًا الآن ... COUNT (1) مقابل COUNT (*) هي أسطورة أخرى تم ضبطها أيضًا.

20
gbn

يجب إعادة صياغة الاستعلام تمامًا

حاول تنفيذ عبارات WHERE سابقًا و JOINs لاحقًا

Select Count(1) from DetailsTable dt
join (Select UserId,Id FROM MasterTable where
created between @date1 and @date2) mt on mt.Id = dt.MasterId 
join (Select Id FROM UserTable WHERE Role is NULL) ut
on ut.Id = mt.UserId;

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

حصلت على هذه الفكرة من فيديو يوتيوب هذا .

لقد جربت المبادئ من الفيديو في سؤال معقد جدًا في StackOverflow وحصلت على مكافأة 200 نقطة.

ذكرgbn التأكد من أن لديك الفهارس الصحيحة. في هذه الحالة ، يرجى فهرسة العمود الذي تم إنشاؤه في MasterTable.

جربها !!!

تحديث 2011-06-24 22:31 بتوقيت شرق الولايات المتحدة

يجب عليك تشغيل هذه الاستعلامات:

SELECT COUNT(1) AllRoles FROM UserTable;
SELECT COUNT(1) NullRoles FROM UserTable WHERE Role is NULL;

إذا كانت NullRoles X 20 <AllRoles (بعبارة أخرى ، إذا كانت NullRoles أقل من 5٪ من صفوف الجدول) ، فيجب عليك إنشاء فهرس غير فريد هو الدور في UserTable. خلاف ذلك ، يكفي جدول كامل من UserTable حيث قد يستبعد محسن الاستعلام استخدام فهرس.

تحديث 2011-06-25 12:40 بتوقيت شرق الولايات المتحدة

نظرًا لأنني MySQL DBA ، فإن أسلوبي في القيام بالأشياء يتطلب عدم الثقة في MySQL Query Optimizer من خلال التشاؤم الإيجابي والمحافظة. وبالتالي ، سأحاول إعادة هيكلة استعلام أو إنشاء فهارس تغطية ضرورية للتغلب على العادات السيئة الخفية لمحسن استعلام MySQL. تبدو إجابة @ gbn أكثر اكتمالاً في أن SQL Server قد يكون لديه المزيد من "سلامة العقل" في تقييم الاستعلامات.

6
RolandoMySQLDBA

كان لدينا جدول [التفاصيل] حول 75 مليون صف ؛ جدول [رئيسي] يحتوي على 400 ألف صف وجدول [عنصر] ذي صلة به 7 صفوف دائمًا وإلى الأبد. قام بتخزين مجموعة صغيرة من "أرقام العناصر" (1-7) وكان يصمم نموذجًا ورقيًا ، تم طباعة ملايين منها وتوزيعها كل شهر. كان أسرع طلب بحث هو الذي قد لا تفكر فيه على الأرجح أولاً ، والذي ينطوي على استخدام صلة ديكارتية. كان المركز مثل:

SELECT m.order_id, i.line_nr, d.Item_amt
FROM Master m, Item i 
INNER JOIN Detail d ON m.order_id = d.order_id

على الرغم من وجود ارتباط "معرف" منطقي بين [Item] و [Detail] ، فقد عمل CROSS JOIN بشكل أفضل من INNER JOIN.

كان RDBMS Teradata بتقنية MPP ، و IDR ما كان مخطط الفهرسة. لا يحتوي الجدول المكون من 7 صفوف على فهرس حيث كان TABLE SCAN دائمًا الأفضل.

1
Timothy Oleary