قاعدة بيانات مكونة من عمودين منطقيين أو فهرس، أو قم بإنشاء جدول "فهرس" منفصل

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

سؤال

لدي هذا الجدول التالي:

Matches -> match_id, team_a_id , team_b_id, score

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

select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);

هل هناك أي نهج أفضل لمثل هذه الحالة؟بالنسبة للاستعلام أعلاه، هل أنا على حق في تضمين فهرس المجموعة team_a_id وteam_b_id؟ولكن على الرغم من ذلك، لا يزال لدي شرط منطقي أو بين AB أو BA.

بدلاً عن ذلك، لدي فكرة أخرى ، هي أن يكون هناك طاولة أخرى دعها تقول التاريخ

History -> team_hash, match_id

أقوم يدويًا ببناء team_hash حيث hash(a,b) == hash(b,a).ولكن هذا يؤدي إلى إدراج أبطأ قليلاً ولكن قراءة أسرع.أم أنها حقا أسرع قراءة؟

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

المحلول

على افتراض وجود مؤشر مركب على {team_a_id, team_b_id}, ، يمكن لنظام إدارة قواعد البيانات (DBMS) تنفيذ عبارة SQL الخاصة بك باستخدام فهرسين فقط (واحد لـ team_a_id = 1 and team_b_id = 2 والآخر ل team_a_id = 2 and team_b_id = 1)، وهو سريع جدًا.لا أتوقع أن تجد الأداء ناقصًا.


ومع ذلك، هناك طريقة لإزالة أحد هذه الفهرس الذي يبحث عنه.إضافة قيد...

CHECK(team_a_id < team_b_id)

... وترميز "الاتجاه" (أيأي فريق هو المضيف) في حقل منفصل إذا لزم الأمر.بهذه الطريقة، كما تعلمون team_a_id = 2 and team_b_id = 1 لا يمكن أن يكون صحيحًا أبدًا، لذلك ما عليك سوى البحث team_a_id = 1 and team_b_id = 2.


التجزئة "المتماثلة" هي فكرة رائعة، ولكن:

  • لا يمكن فرض صحة التجزئة بشكل تصريحي - ستحتاج إلى القيام بذلك من خلال مشغل أو على مستوى التطبيق.
  • إنها بيانات زائدة عن الحاجة.سوف تحتاج إلى الاحتفاظ بها team_a_id و team_b_id على أي حال لحل تعارضات التجزئة.البيانات الأكبر حجمًا تعني بشكل فعال ذاكرة تخزين مؤقت أصغر.
  • قد يؤدي ذلك في الواقع إلى زيادة عدد الفهارس - ربما يتطلب التنفيذ الفعال للتكامل المرجعي تشغيل الفهارس team_a_id و team_b_id حتى لو لم تكن بحاجة إليها لاستعلام SQL الفعلي.بالإضافة إلى الضغط بشكل أكبر على ذاكرة التخزين المؤقت، يجب الحفاظ على كل فهرس إضافي، مما قد يؤدي إلى الإضرار بأداء INSERT/UPDATE/DELETE.يعد الوضع خطيرًا بشكل خاص في InooDB حيث لا يمكنك إيقاف تشغيل التجميع، لذا تميل الفهارس الثانوية إلى أن تكون أكثر تكلفة من الجداول المستندة إلى الكومة (راجع "عيوب التجميع" في هذا المقال).

نصائح أخرى

يمكنك أيضًا جعل جملة WHERE الخاصة بك شيئًا كهذا

((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1))
AND team_a_id IN (1,2) AND team_b_id IN (1,2)

بهذه الطريقة سيكون من الممكن استخدام فهرس مثل (team_a_id,team_b_id).

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