دمج الفهارس
إنه أحد أكثر الأسئلة شيوعاً عن الفهرسة: هل الأفضل إنشاء فهرس لكل عمود أم فهرس واحد لجميع أعمدة عبارة where؟ الجواب بسيط جداً في معظم الحالات: فهرس واحد متعدد الأعمدة أفضل—أي فهرس مُسلسل أو مركّب. ويشرح «المفاتيح المُسلسلة» ذلك بالتفصيل.
ومع ذلك توجد استعلامات لا يستطيع فهرس واحد أداء مهمته فيها أداءً مثالياً، مهما عرّفت الفهرس؛ مثل الاستعلامات ذات شرطي نطاق مستقلين أو أكثر كما في المثال التالي:
SELECT first_name, last_name, date_of_birth
FROM employees
WHERE UPPER(last_name) < ?
AND date_of_birth < ?
من المستحيل تعريف فهرس شجرة B (B-tree index) يدعم هذا الاستعلام دون مُسندات ترشيح. وللتوضيح، يكفي أن تتذكر أن الفهرس قائمة مترابطة.
إذا عرّفت الفهرس بـUPPER(LAST_NAME) ثم DATE_OF_BIRTH (بهذا الترتيب)، تبدأ القائمة بـA وتنتهي بـZ. ولا يُراعى تاريخ الميلاد إلا عند وجود موظفين لهما الاسم نفسه. وإذا عرّفت الفهرس بالترتيب المعاكس، فسيبدأ بأكبر الموظفين سناً وينتهي بأصغرهم. وفي هذه الحالة يكون للأسماء تأثير ضئيل في ترتيب الفرز.
ومهما لويت تعريف الفهرس وبدّلته، تبقى المدخلات مرتّبة على سلسلة. في أحد الطرفين المدخلات الصغيرة وفي الطرف الآخر المدخلات الكبيرة. لذا لا يمكن للفهرس دعم سوى شرط نطاق واحد كمُسند وصول. ودعم شرطي نطاق مستقلين يتطلب محوراً ثانياً، مثلاً مثل رقعة شطرنج. حينها سيطابق الاستعلام أعلاه جميع المدخلات من زاوية واحدة من رقعة الشطرنج، لكن الفهرس ليس مثل رقعة شطرنج—إنه مثل سلسلة. ولا توجد زاوية.
إن أعجبك هذا الموضوع، قد يعجبك أيضاً…
… أن تشترك في القوائم البريدية، وتحصل على ملصقات مجانية، وتشتري كتابي، أو تنضم إلى دورة تدريبية.
يمكنك بالطبع قبول مُسند الترشيح واستخدام فهرس متعدد الأعمدة مع ذلك. وهذا أفضل حل في معظم الحالات على أي حال. وينبغي أن يذكر تعريف الفهرس العمود الأكثر انتقائية أولاً ليُستخدم كمُسند وصول. وقد يكون ذلك أصل خرافة «الأكثر انتقائية أولاً»، لكن هذه القاعدة لا تصح إلا إذا لم تستطع تجنّب مُسند ترشيح.
والخيار الآخر هو استخدام فهرسين منفصلين، واحد لكل عمود. حينها يجب على قاعدة البيانات مسح الفهرسَين أولاً ثم دمج النتائج. فمجرد البحث المزدوج بالفهرس ينطوي على جهد أكبر لأن قاعدة البيانات يجب أن تجتاز شجرتي فهرس. وإضافة إلى ذلك، تحتاج قاعدة البيانات إلى ذاكرة كبيرة ووقت CPU لدمج النتائج الوسيطة.
ملاحظة
مسح فهرس واحد أسرع من مسحين.
تستخدم قواعد البيانات طريقتين لدمج الفهارس. أولاً هناك ضمّ الفهارس (index join). ويشرح الفصل 4عملية الضمّ الخوارزميات المتصلة بالتفصيل. والنهج الثاني يستفيد من وظائف من عالم مستودع البيانات (data warehouse).
مستودع البيانات هو أم جميع الاستعلامات المخصّصة. فهو يحتاج بضع نقرات فقط لدمج شروط اعتباطية في الاستعلام الذي تختاره. ومن المستحيل توقّع تركيبات الأعمدة التي قد تظهر في عبارة where، وهذا يجعل الفهرسة، كما شُرحت حتى الآن، شبه مستحيلة.
وتستخدم مستودعات البيانات نوعاً خاصاً من الفهارس لحل هذه المشكلة: ما يسمى الفهرس النقطي (bitmap index). وميزة الفهارس النقطية أنها قابلة للدمج بسهولة نسبية. ويعني ذلك حصولك على أداء جيد عند فهرسة كل عمود على حدة. وعلى العكس، إذا كنت تعرف الاستعلام مسبقاً بحيث يمكنك إنشاء فهرس شجرة B متعدد الأعمدة مفصّل، فسيظل أسرع من دمج عدة فهارس نقطية.
وأكبر نقاط ضعف الفهارس النقطية بفارق كبير هو قابلية التوسع السخيفة لعمليات insert وupdate وdelete. فعمليات الكتابة المتزامنة شبه مستحيلة. ولا يمثّل ذلك مشكلة في مستودع البيانات لأن عمليات التحميل تُجدول واحدة تلو الأخرى. أما في التطبيقات المتصلة بالإنترنت، فالفهارس النقطية عديمة الفائدة في الغالب.
مهم
الفهارس النقطية شبه غير قابلة للاستخدام في المعالجة المعاملاتية الآنية (online transaction processing — OLTP).
تقدم منتجات قواعد بيانات كثيرة حلاً هجيناً بين فهارس شجرة B والفهارس النقطية. وعند غياب مسار وصول أفضل، تحوّل نتائج عدة مسوحات شجرة B إلى بنى نقطية في الذاكرة. وهذه قابلة للدمج بكفاءة. ولا تُخزَّن البنى النقطية تخزيناً دائماً بل تُهمل بعد تنفيذ العبارة، وبذلك تُتجاوز مشكلة قابلية الكتابة الضعيفة. والعيب أنها تحتاج ذاكرة كبيرة ووقت CPU. وهذه الطريقة، في النهاية، من فعل يأس المُحسِّن (optimizer).