labZero:~$ ESC
  • لا نتائج…
↑↓ تنقّل·Enter اذهب·⌘K

labZero:~$ cd ./lab / lab-mysql-optimizer-skip...

المختبر
v0.1 قابل للاستخدام 4 يونيو 2026

الـ Query Optimizer يتجاهل الفهرس — متى تصبح الأرقام أهم من الخطة؟

استعلام على جدول 200K صف مع `INDEX(status)` — الـ optimizer اختار Full Table Scan. السبب: 78% من الصفوف بنفس القيمة.

#MySQL #Laravel #Performance

// في هذا المقال

السياق

جدول orders بـ 200 ألف صف. عمود status يأخذ ثلاث قيم: pending (4K صف)، completed (156K)، cancelled (40K). استعلام WHERE status = 'pending' ORDER BY created_at مع INDEX(status) يأخذ 1.2 ثانية. EXPLAIN يُظهر type=ALL — Full Table Scan رغم الفهرس.

الإجراء

شغّلت SHOW INDEX FROM orders — cardinality = 3، وهو عدد القيم المختلفة فقط. استخدمت FORCE INDEX(status) — الاستعلام أبطأ بـ 40%! قارنت ثلاثة سيناريوهات: (أ) INDEX(status) المنفرد، (ب) INDEX(status, created_at) المركّب، (ج) ANALYZE TABLE لتحديث الإحصائيات. راقبت EXPLAIN FORMAT=JSON لقراءة rows_examined الفعلي.

النتيجة

الـ optimizer اختار الفهرس لـ pending (2% من الصفوف) وتجاهله لـ completed (78%). الفهرس المركّب (status, created_at) استُخدم في كلا الحالتين لأنه أتاح index-only scan مع أمر الفرز. ANALYZE TABLE حدّث الإحصائيات وحسّن الخطة لـ pending تلقائياً.

الدرس

الـ optimizer يعرف ما لا تعرفه — قبل بناء فهرس على عمود حالة، افحص توزيع القيم الحقيقي، وفكّر في فهرس مركّب يشمل عمود الفرز.

هل تشبه فكرتك هذا المشروع؟ باب التعاون من هنا ‹