MySQL: مقدمة إلى استعلامات MySQL وخطة التنفيذ EXPLAIN
آخر تحديث: 2026-08-26
لا يمكنك كتابة استعلامات عالية الأداء حقًّا إلا إذا فهمت الميزات المتقدمة للفهارس.
يقدم هذا الدرس شرحًا متعمقًا لأنواع الفهارس وتحليل EXPLAIN.
1. ما ستتعلمه
- الفهرس المجمَّع مقابل الفهرس غير المجمَّع
- مؤشر التغطية
- المؤشرات المركبة والبادئة الموجودة في أقصى اليسار
- الحالات التي تصبح فيها الفهارس غير نشطة
- تفسير خطة التنفيذ في EXPLAIN
2. الفهارس المجمعة والفهارس غير المجمعة
| البعد | الفهرس المجمَّع | الفهرس غير المجمَّع |
|---|---|---|
| طريقة التخزين | يتم تخزين البيانات والفهارس معًا | تشير الفهارس إلى عناوين البيانات |
| الكمية | يُسمح بواحد فقط | يُسمح بعدة قطع |
| المفتاح الأساسي | يستخدم InnoDB المفتاح الأساسي تلقائيًا | الفهرس الثانوي |
| الاستعلام | استرجاع البيانات مباشرة | يتطلب البحث في الجدول |
(1) البحث في جدول
graph LR
A[Secondary Index<br/>idx_email] -->|Primary Key Value| B[Clustered Index<br/>PRIMARY]
B -->|Complete Data| C[Data Row]
SQL
-- The process of table lookup
SELECT * FROM users WHERE email = 'alice@email.com';
-- 1. Find id=1 in idx_email
-- 2. Find complete data for id=1 in PRIMARY
3. مؤشرات التغطية
جميع الحقول الموجودة في الاستعلام مدرجة في الفهرس، لذا لا داعي للرجوع إلى الجدول.
▶ مثال: مؤشر التراكب
SQL
-- Create a composite index
CREATE INDEX idx_name_email ON users(username, email);
-- Covering Index(No need to return to the table)
SELECT username, email FROM users WHERE username = 'alice';
-- Non-covering index(Need to return to the table)
SELECT * FROM users WHERE username = 'alice';
| النوع | العودة إلى الجدول | الأداء |
|---|---|---|
| فهرس التغطية | رقم | سريع |
| فهرس غير شامل | نعم | بطيء |
4. المؤشرات المركبة والبادئة الموجودة في أقصى اليسار
(1) مبدأ البادئة الموجودة في أقصى اليسار
يمكن استخدام المؤشر المركب (a, b, c) في الاستعلامات التالية:
SQL
WHERE a = 1 -- ✅ Using index
WHERE a = 1 AND b = 2 -- ✅ Using index
WHERE a = 1 AND b = 2 AND c = 3 -- ✅ Using index
WHERE b = 2 -- ❌ Index not used
WHERE b = 2 AND c = 3 -- ❌ Index not used
▶ مثال: التحقق من استخدام الفهرس
SQL
CREATE INDEX idx_abc ON orders(customer_id, status, order_date);
-- ✅ Using index
EXPLAIN SELECT * FROM orders WHERE customer_id = 1;
EXPLAIN SELECT * FROM orders WHERE customer_id = 1 AND status = 'paid';
EXPLAIN SELECT * FROM orders WHERE customer_id = 1 AND status = 'paid' AND order_date > '2026-01-01';
-- ❌ Index not used (Violates the Leftmost Prefix Rule)
EXPLAIN SELECT * FROM orders WHERE status = 'paid';
5. الحالات التي تصبح فيها الفهارس غير فعالة
| السيناريو | المثال | السبب |
|---|---|---|
| عمليات الدوال | WHERE YEAR(date) = 2026 |
الفهرس المحاط بدالة |
| التحويل الضمني | WHERE phone = 13800001111 |
الاستعلام عن مصفوفات السلاسل باستخدام الأرقام |
| LIKE Left Fuzzy | WHERE name LIKE '%john' |
البادئة غير مؤكدة |
| شرط OR | WHERE a = 1 OR b = 2 |
بعض الحقول غير مفهرسة |
| غير موجود/غير موجود | WHERE id NOT IN (1,2) |
يختار المُحسِّن إجراء مسح كامل للجدول |
| IS NULL/IS NOT NULL | WHERE col IS NULL |
يعتمد على نسبة القيم NULL |
▶ مثال: فشل الفهرس والاستعادة
SQL
-- ❌ Index Invalidation
SELECT * FROM users WHERE YEAR(created_at) = 2026;
-- ✅ Fix: Change to a range query
SELECT * FROM users WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01';
-- ❌ Index Invalidation
SELECT * FROM users WHERE phone = 13800001111;
-- ✅ Fix: Use quotes
SELECT * FROM users WHERE phone = '13800001111';
6. شرح خطة التنفيذ
▶ مثال: استخدام EXPLAIN
SQL
EXPLAIN SELECT * FROM users WHERE email = 'alice@email.com';
الناتج:
TEXT
📖 للعرض فقط
+----+-------+------+---------+------+----------+-------+
| id | type | key | key_len | ref | rows | Extra |
+----+-------+------+---------+------+----------+-------+
| 1 | const | idx_email | 402 | const | 1 | |
+----+-------+------+---------+------+----------+-------+
(1) وصف الحقول الرئيسية
| الحقل | الوصف | القيم الصالحة |
|---|---|---|
| النوع | نوع الوصول | const > eq_ref > ref > range > index > ALL |
| المفتاح | الفهرس المستخدم | غير NULL |
| الصفوف | العدد التقديري للصفوف المطلوب مسحها | كلما كان الرقم أقل، كان ذلك أفضل |
| إضافي | معلومات إضافية | استخدام الفهرس (الفهرس الشامل) |
(2) نوع الوصول
| النوع | الوصف | الإيجابيات والسلبيات |
|---|---|---|
| ثابت | استعلامات المساواة للمفتاح الأساسي/الفهرس الفريد | ⭐⭐⭐ |
| eq_ref | استخدام المفتاح الأساسي/الفهرس الفريد في عمليات الربط | ⭐⭐⭐ |
| المرجع | استعلامات المساواة على الفهارس غير الفريدة | ⭐⭐ |
| النطاق | استعلام نطاق الفهرس | ⭐⭐ |
| الفهرس | المسح الكامل للفهرس | ⭐ |
| الكل | مسح كامل للجدول | ❌ |
❓ أسئلة شائعة
س كيف يجب أن أختار ترتيب الحقول في الفهرس المركب؟
ج ضع الحقول ذات الانتقائية العالية أولاً، وكذلك الحقول التي يتم الاستعلام عنها بشكل متكرر أولاً.
س هل قيم «rows» في EXPLAIN دقيقة؟
ج إنها تقديرات وليست قيمًا دقيقة. ومع ذلك، يمكن استخدامها لتقييم كفاءة الاستعلام.
س ماذا عليّ أن أفعل إذا أصبح الفهرس غير فعال؟
ج أعد كتابة جملة SQL لتجنب الحالات التي يصبح فيها الفهرس غير فعال، أو أنشئ فهرسًا وظيفيًّا (MySQL 8.0 وما بعده).
س هل قيم «rows» في EXPLAIN دقيقة؟
ج إنها تقديرات وليست قيمًا دقيقة، لكن يمكنك تقييم فعالية عمليات التحسين من خلال مقارنة التغيرات النسبية. استخدم الأمر ANALYZE TABLE لتحديث الإحصائيات.
س متى ينبغي استخدام فهرس البادئة؟
ج عندما يكون حقل VARCHAR طويلاً جدًّا وتكون البادئة مميزة بدرجة كافية. على سبيل المثال،
INDEX(email(10)) — شريطة أن تبلغ درجة تمييز الأحرف العشرة الأولى أكثر من 95%.📖 ملخص
- الفهارس المجمعة تخزن البيانات والفهارس معًا، بينما تتطلب الفهارس غير المجمعة البحث في الجدول.
- فهرس شامل: يتم تضمين جميع حقول الاستعلام في الفهرس، لذا لا توجد حاجة للرجوع إلى الجدول.
- البادئة الموجودة في أقصى اليسار: يتم البحث في الفهرس المركب من اليسار إلى اليمين
- سيناريوهات إبطال الفهرس: الدوال، التحويلات الضمنية، التعميم الأيسر، أو
- EXPLAIN تحليل خطة الاستعلام، مع التركيز على النوع/المفتاح/الصفوف
📝 تمارين
-
سؤال أساسي (مستوى الصعوبة: ⭐): استخدم
EXPLAINلتحليل استعلام ما وتحديد ما إذا كان يتم استخدام فهرس أم لا. -
مشكلة متقدمة (درجة الصعوبة ⭐⭐): أنشئ فهرسًا مركبًا للتحقق من مبدأ البادئة الموجودة في أقصى اليسار.
-
سؤال التحدي (مستوى الصعوبة: ⭐⭐⭐): حدد ثلاثة سيناريوهات تكون فيها الفهارس غير فعالة واقترح حلولاً لها.