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

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

المقايضات في فهارس قواعد البيانات

بينما تسرع الفهارس عمليات القراءة، فإنها تقدم تكاليف في أماكن أخرى. يجب تحديث الفهرس مع كل عملية INSERT أو UPDATE أو DELETE، مما يبطئ أداء الكتابة. بالإضافة إلى ذلك، تستهلك الفهارس مساحة القرص والذاكرة. الجدول الذي يحتوي على ثمانية فهارس يتطلب الحفاظ على تسعة هياكل بيانات منفصلة بدلاً من واحد، مما يزيد من ضغط الذاكرة المؤقتة ومتطلبات التخزين.

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

الأخطاء الشائعة والحلول

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

تؤدي الدوال المطبقة على الأعمدة المفهرسة أيضاً إلى إلغاء استخدام الفهرس. لا يمكن لاستعلام يستخدم lower(name) = ‘value’ استخدام فهرس على العمود name الخام، لأن قاعدة البيانات ترى lower(name) كتعبير مختلف تماماً. ينطبق الشيء نفسه على تحويلات النوع الضمنية. يتضمن الحل إنشاء فهرس وظيفي على التعبير نفسه: CREATE INDEX ON table (lower(column)).

أنواع الفهارس المتقدمة

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

تحتوي الفهارس الشاملة على جميع الأعمدة التي يحتاجها الاستعلام، مما يسمح لقاعدة البيانات بالإجابة على الاستعلام من الفهرس وحده دون الوصول إلى الجدول. عند عرضها باستخدام EXPLAIN، يظهر هذا كـ Index Only Scan. يدعم Postgres جملة INCLUDE لإضافة أعمدة غير رئيسية إلى فهرس لأغراض الشمول دون إجبار قاعدة البيانات على الفرز حسب تلك الأعمدة.

قياس فعالية الفهرس

بدلاً من التخمين حول ما إذا كان الفهرس مفيداً، قم بقياس الأداء الفعلية باستخدام أدوات قاعدة البيانات. يوفر Postgres أداة EXPLAIN التي تعرض خطة الاستعلام دون تنفيذها. يشير Index Scan إلى أن الفهرس قيد الاستخدام؛ يعني Seq Scan أن قاعدة البيانات تقرأ كل صف. يقوم EXPLAIN ANALYZE بتشغيل الاستعلام فعلياً والإبلاغ عن التوقيتات الفعلية، مما يكشف غالباً عن نتائج مفاجئة حول سلوك الاستعلام.

يؤثر الفهرسة الذكية بشكل مباشر على أداء قاعدة البيانات واستجابة التطبيق. يمكّن فهم آليات الفهرس والمقايضات والأخطاء الشائعة المطورين من اتخاذ قرارات مستنيرة بدلاً من إنشاء الفهارس بشكل استجابي أو تركها بالكامل. يمنع الاختبار باستخدام EXPLAIN قبل نشر الفهارس في الإنتاج إهدار الموارد ويضمن تنفيذ الاستعلام الأمثل.

المصدر: jon.chrt.dev