MySQL: تحسين أداء MySQL
آخر تحديث: 2026-08-26
خلال فترة التخفيضات السنوية، شهدت منصة التجارة الإلكترونية الخاصة بشركة «أليس» ارتفاعًا حادًّا في زمن استجابة قاعدة البيانات من 50 مللي ثانية إلى 5 ثوانٍ، حيث اشتكى المستخدمون من عدم تحميل الصفحات ومن انتهاء مهلة إرسال الطلبات. أجرى فريق العمليات تحقيقًا عاجلًا واكتشف أن عدة استعلامات بطيئة غير مُحسَّنة كانت تتسبب في إبطاء النظام بأكمله بشكل كبير. ومن خلال تمكين تسجيل الاستعلامات البطيئة لتحديد عبارات SQL التي تنطوي على مشاكل، وتحليل خطط التنفيذ باستخدام EXPLAIN، وإضافة الفهارس المفقودة، وإعادة كتابة الاستعلامات غير الفعالة، وضبط معلمات تكوين InnoDB، تمكن الفريق في النهاية من تقليل وقت الاستجابة إلى أقل من 100 مللي ثانية.
1. ما ستتعلمه
- طرق تكوين سجلات الاستعلامات البطيئة وجمعها وتحليلها
- تحليل متعمق للحقول الموجودة في خطة التنفيذ EXPLAIN (type/key/rows/Extra)
- الاستراتيجيات الأساسية لتحسين الفهارس: تجنب الفهارس غير الصالحة، والفهارس الشاملة، والبادئة الموجودة في أقصى اليسار من الفهارس المركبة
- تقنيات إعادة صياغة الاستعلامات: تجنب
SELECT *، واستبدال الاستعلامات الفرعية بـJOIN، وتحسين الترقيم العميق للصفحات - ضبط معلمات التكوين الرئيسية: innodb_buffer_pool_size، max_connections، وما إلى ذلك.
2. عملية تحسين الأداء من البداية إلى النهاية
تحسين الأداء ليس مهمة تُنفَّذ مرة واحدة، بل هو عملية دورية تتألف من «الاكتشاف → التحليل → التحسين → التحقق».
flowchart TD
A[Identifying Slow Queries] --> B[EXPLAIN Analyze the Execution Plan]
B --> C{Issue Type?}
C -->|Missing Index| D[Index Optimization]
C -->|Inefficient query syntax| E[Query Rewrite]
C -->|Unreasonable configuration| F[Configuration Tuning]
D --> G[Verifying Performance Improvements]
E --> G
F --> G
G -->|Still does not meet the standards| A
G -->|Meet the requirements| H[Deployment Monitoring]
3. سجل الاستعلامات البطيئة
يُعد سجل الاستعلامات البطيئة خط الدفاع الأول لتحديد مشكلات الأداء؛ حيث يقوم تلقائيًا بتسجيل عبارات SQL التي يتجاوز وقت تنفيذها حدًا معينًا.
(1) البدء والتكوين
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
(2) أدوات تحليل السجلات
mysqldumpslow هي أداة تجميع سجلات الاستعلامات البطيئة المدمجة في MySQL، والتي تقوم بفرز الاستعلامات حسب وقت التنفيذ أو التكرار.
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log
(3) البدائل لمخطط الأداء
يدعم MySQL 5.6 والإصدارات الأحدث استخدام «Performance Schema» لجمع الاستعلامات البطيئة، ويمكن تفعيل هذه الميزة ديناميكيًا دون الحاجة إلى تعديل ملف التكوين.
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES' WHERE NAME = 'events_statements_history_long';
▶ مثال: تمكين سجل الاستعلامات البطيئة وتحديد أهم 5 استعلامات بطيئة
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 0.5;
SET GLOBAL min_examined_row_limit = 100;
SHOW VARIABLES LIKE 'slow_query_log_file';
mysqldumpslow -s t -t 5 /var/lib/mysql/slow.log
▶ مثال: عرض الاستعلامات البطيئة بسرعة باستخدام عرض sys
SELECT query_id, LEFT(query, 80) AS query_text,
exec_count, avg_timer_ms, rows_examined
FROM sys.statements_with_runtimes_in_95th_percentile
ORDER BY avg_timer_ms DESC LIMIT 10;
4. تحليل متعمق لخطة التنفيذ في EXPLAIN
تعد وظيفة EXPLAIN الأداة التشخيصية الأكثر أهمية في عملية تحسين أداء SQL؛ فهي توضح كيفية تنفيذ MySQL للاستعلامات.
(1) نظرة عامة على حقول مخرجات EXPLAIN
| الحقل | المعنى | النقاط الرئيسية |
|---|---|---|
| id | رقم الاستعلام | ترتيب تنفيذ الاستعلامات الفرعية |
| select_type | نوع الاستعلام | تجنب DERIVED و UNCACHEABLE |
| الجدول | الجدول الذي تم الوصول إليه | عدد الجداول ذات الصلة |
| النوع | نوع الوصول | من «النظام» إلى «الجميع»؛ كلما كان أقرب إلى اليسار، كان ذلك أفضل |
| possible_keys | الفهارس المحتملة | اختيار الفهرس بناءً على المقارنة مع المفتاح |
| المفتاح | الفهرس المستخدم فعليًّا | تشير القيمة NULL إلى عدم استخدام أي فهرس |
| key_len | طول الفهرس | يحدد عدد الحقول المستخدمة في الفهرس المركب |
| الصفوف | العدد التقديري للصفوف المطلوب مسحها | كلما كان الرقم أقل، كان ذلك أفضل |
| إضافي | معلومات إضافية | استخدام filesort/استخدام الملفات المؤقتة — يحتاج إلى تحسين |
(2) شرح تفصيلي لحقل «type»
يُعد الحقل type الحقل الأكثر أهمية في EXPLAIN؛ فهو يعكس بشكل مباشر كفاءة الاستعلام.
| النوع | المعنى | طريقة المسح | تقييم الأداء |
|---|---|---|---|
| النظام | صف واحد فقط في الجدول | القراءة المباشرة | ★★★★★ |
| ثابت | استعلامات المساواة للمفتاح الأساسي/الفهرس الفريد | تطابق صف واحد على الأكثر | ★★★★★ |
| eq_ref | المفتاح الأساسي/الفهرس الفريد في عملية الربط | يربط صفًا واحدًا بكل صف | ★★★★☆ |
| المرجع | استعلامات المساواة على الفهارس غير الفريدة | تطابق عدة صفوف | ★★★☆☆ |
| النطاق | مسح نطاق الفهرس | BETWEEN/IN/>/< | ★★★☆☆ |
| الفهرس | المسح الكامل للفهرس | التنقل عبر شجرة الفهرس بأكملها | ★★☆☆☆ |
| الكل | مسح الجدول بالكامل | التمرير عبر الجدول بأكمله | ★☆☆☆☆ |
(3) قيم مفاتيح الحقول الإضافية
Using index: مؤشر التغطية؛ لا حاجة للرجوع إلى الجدول؛ أفضل أداءUsing where: بعد أن يقوم محرك التخزين بإرجاع البيانات، يتم تصفية هذه البيانات بواسطة طبقة الخادمUsing filesort: يتعذر الفرز باستخدام الفهرس؛ يلزم إجراء عملية فرز إضافية.Using temporary: تم استخدام جدول مؤقت؛ وهذا أمر شائع عندما لا يكون لعبارة GROUP BY فهرس.Using index condition: دفع الفهرس (ICP)، مما يقلل من عدد عمليات البحث في الجداول
▶ مثال: تحليل استعلام على جدول واحد باستخدام EXPLAIN
EXPLAIN SELECT order_id, user_id, total_amount
FROM orders
WHERE user_id = 42 AND status = 'PAID';
+----+-------------+--------+------+---------------+------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-----------------------+
| 1 | SIMPLE | orders | ref | idx_user | idx_user | 4 | 120 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+------+-----------------------+
▶ مثال: تحليل استعلام مدمج باستخدام EXPLAIN
EXPLAIN SELECT o.order_id, u.username
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.create_time > '2025-01-01';
5. استراتيجيات تحسين الفهرس
تعد الفهارس أدوات فعالة لتسريع عمليات الاستعلام، لكن استخدام الفهرس الخاطئ أخطر من عدم وجود فهرس على الإطلاق.
(1) مؤشر التغطية
الفهرس الشامل هو الفهرس الذي تتضمن جميع الحقول المستخدمة في الاستعلام، مما يلغي الحاجة إلى الوصول إلى الجدول لقراءة بيانات الصفوف.
ALTER TABLE orders ADD INDEX idx_cover (user_id, status, total_amount);
يسترد الاستعلام عن SELECT user_id, status, total_amount FROM orders WHERE user_id = 42 البيانات بالكامل من الفهرس.
(2) المؤشرات المركبة والبادئة الموجودة في أقصى اليسار
تتبع الفهارس المركبة مبدأ البادئة الموجودة في أقصى اليسار: يجب أن تبدأ شروط الاستعلام في المطابقة من العمود الموجود في أقصى يسار الفهرس.
ALTER TABLE orders ADD INDEX idx_user_status_time (user_id, status, create_time);
| شروط الاستعلام | هل يمكن الوصول إلى الفهرس؟ | السبب |
|---|---|---|
| WHERE user_id = 1 | ✅ | يتطابق مع العمود الأيسر |
| WHERE user_id = 1 AND status = 'PAID' | ✅ | تتطابق مع العمودين الأولين |
| WHERE user_id = 1 AND create_time > '2025-01-01' | ⚠️ | يقتصر البحث على user_id، ويتجاهل الحالة |
| WHERE status = 'PAID' | ❌ | العمود الأيسر user_id مفقود |
(3) مرجع سريع لسيناريوهات فشل الفهرس
| سيناريوهات الفشل | صيغة غير صحيحة | صيغة صحيحة |
|---|---|---|
| استخدام الدوال على الأعمدة المفهرسة | WHERE YEAR(create_time) = 2025 |
WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01' |
| التحويل الضمني للأنواع | WHERE varchar_col = 123 |
WHERE varchar_col = '123' |
| البحث الضبابي عن اليسار | WHERE name LIKE '%alice' |
WHERE name LIKE 'alice%' |
| عملية OR تربط بين أعمدة غير مفهرسة | WHERE indexed_col = 1 OR unindexed = 2 |
قم بتقسيمها إلى عملية UNION أو أضف فهرسًا إلى العمود غير المفهرس |
| لا يساوي | WHERE status != 'PAID' |
WHERE status IN ('UNPAID', 'CANCELLED') |
| أعمدة الفهرس المستخدمة في الحسابات | WHERE id + 1 = 100 |
WHERE id = 99 |
▶ مثال: التحقق من صحة البادئة الموجودة في أقصى اليسار لمؤشر مركب
ALTER TABLE products ADD INDEX idx_cat_brand_price (category_id, brand_id, price);
EXPLAIN SELECT * FROM products WHERE category_id = 5 AND brand_id = 10;
EXPLAIN SELECT * FROM products WHERE brand_id = 10;
يحتوي الاستعلام الثاني على type من ALL لأنه يتخطى العمود الموجود في أقصى اليسار، category_id.
▶ مثال: استخدام فهرس تغطية لتجنب عمليات البحث في الجداول
ALTER TABLE orders ADD INDEX idx_user_status_amount (user_id, status, total_amount);
EXPLAIN SELECT user_id, status, total_amount
FROM orders WHERE user_id = 42;
إذا ظهر Using index في عمود «إضافي»، فهذا يعني أنه لا حاجة إلى البحث في الجدول.
6. تقنيات تحسين الاستعلامات
حتى مع وجود فهرس، لا تزال الاستعلامات المكتوبة بشكل سيئ غير قادرة على الاستفادة منه.
(1) تجنب استخدام SELECT *
تؤدي عبارة SELECT * إلى قراءة جميع الأعمدة، وتزيد من عمليات الإدخال/الإخراج (I/O)، وقد تؤدي إلى فقدان الفعالية للفهرس الشامل.
SELECT id, username, email FROM users WHERE id = 100;
(2) إعادة كتابة الاستعلامات الفرعية على شكل أوامر JOIN
يتم تنفيذ الاستعلام الفرعي ذي الصلة مرة واحدة لكل صف؛ ويمكن أن تؤدي إعادة صياغته على شكل JOIN إلى تقليل عدد عمليات المسح بشكل كبير.
SELECT o.order_id, o.total_amount
FROM orders o
WHERE o.user_id IN (SELECT id FROM users WHERE vip_level >= 3);
مُحسَّن لـ:
SELECT o.order_id, o.total_amount
FROM orders o
JOIN users u ON o.user_id = u.id AND u.vip_level >= 3;
(3) التحسين المتعمق لترقيم الصفحات
يُظهر LIMIT offset, n التقليدي أداءً سيئًا للغاية عندما يكون الإزاحة كبيرة.
SELECT * FROM orders ORDER BY id LIMIT 1000000, 10;
خطة التحسين — ترقيم الصفحات باستخدام المؤشر:
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 10;
(4) مرجع سريع لتقنيات تحسين الاستعلامات
| نصائح التحسين | الأنماط غير المرغوب فيها | الممارسات الموصى بها | السيناريوهات القابلة للتطبيق |
|---|---|---|---|
| تجنب استخدام SELECT * | SELECT * |
استعلام عن الأعمدة الضرورية فقط | جميع الاستعلامات |
| تحويل الاستعلامات الفرعية إلى عمليات ربط (JOIN) | WHERE IN (SELECT ...) |
JOIN ... ON ... |
الاستعلامات المرتبطة |
| ترقيم الصفحات باستخدام المؤشر | LIMIT 100000, 10 |
WHERE id > last_id LIMIT 10 |
ترقيم الصفحات المتعمق |
| الإدراج الجماعي | الإدراج بالتتابع عبر السجلات الفردية | INSERT INTO ... VALUES (...),(...),(...) |
استيراد البيانات |
| تجنب المعاملات الكبيرة | عمليات القفل طويلة الأمد | تقسيم المعاملات إلى معاملات أصغر | عمليات الكتابة عالية التزامن |
▶ مثال: مقارنة بين طرق تحسين الترقيم العميق للصفحات
SELECT * FROM orders ORDER BY create_time LIMIT 500000, 20;
مُحسَّن من أجل الارتباط المؤجل:
SELECT o.* FROM orders o
JOIN (SELECT id FROM orders ORDER BY create_time LIMIT 500000, 20) t
ON o.id = t.id;
لا تسترد الاستعلام الفرعي سوى المفتاح الأساسي، ويستخدم فهرسًا شاملاً لتحديد موقع المعرّف بسرعة، ثم يسترد البيانات الكاملة من الجدول.
▶ مثال: تحسين عمليات الإدراج المجمعة
INSERT INTO order_items (order_id, product_id, quantity)
VALUES (1001, 201, 2), (1001, 202, 1), (1001, 203, 5);
بالمقارنة مع تنفيذ جملة INSERT واحدة ثلاث مرات في حلقة، فإن هذا يقلل عدد رحلات الشبكة ذهابًا وإيابًا وحمل عمليات تثبيت المعاملات بمقدار اثنين.
7. تحسين بنية الجداول
يُعد تصميم هيكل الجدول بشكل جيد أساس الأداء؛ ولا يمكن لإعادة كتابة لغة SQL سوى تحسين الهيكل الحالي.
(1) اختيار نوع الحقل
| نوع البيانات | الخيار الموصى به | السبب |
|---|---|---|
| المفتاح الأساسي | BIGINT UNSIGNED | عدد صحيح يتزايد تلقائيًا؛ كفاءة عالية في الإدراج باستخدام أشجار B |
| الحالة/القائمة | TINYINT | تخزين بحجم 1 بايت، يُستخدم مع قيد CHECK |
| المبلغ | DECIMAL(10,2) | احسب بدقة لتجنب أخطاء العدد العائم |
| نص قصير | VARCHAR(N) | يخصص مساحة بناءً على الطول الفعلي |
| نص طويل | نص | يتم تخزينه بشكل منفصل لمنع تأثير الفائض على السجل الرئيسي |
| الوقت | التاريخ والوقت / الطابع الزمني | يشغل الطابع الزمني 4 بايت ولكن نطاقه محدود |
| Boolean | TINYINT(1) | لا يوجد في MySQL نوع BOOLEAN أصلي |
(2) التصميم المضاد للنموذج السائد
في الحالات التي تتسم بارتفاع حجم الاستعلامات، يمكن أن يؤدي وجود قدر معتدل من التكرار إلى تقليل عدد عمليات JOIN.
CREATE TABLE order_summary (
order_id BIGINT PRIMARY KEY,
user_id BIGINT,
username VARCHAR(64),
total_amount DECIMAL(10,2),
INDEX idx_user (user_id)
);
قم بنسخ العمود username في جدول «orders» لتجنب الحاجة إلى إجراء عملية «JOIN» مع جدول users في كل استعلام.
▶ مثال: مقارنة بين طرق تحسين أنواع الحقول
ALTER TABLE products MODIFY COLUMN weight DECIMAL(8,2);
ALTER TABLE products MODIFY COLUMN description TEXT;
قم بتغيير العمود weight من VARCHAR إلى DECIMAL، وقم بتغيير العمود description من VARCHAR(5000) إلى TEXT لتقليل طول السجل الأساسي.
8. ضبط معلمات التكوين
تؤثر معلمات تكوين MySQL بشكل مباشر على سلوك محركات التخزين وتخصيص الموارد.
(1) معلمات التكوين الرئيسية والقيم الموصى بها
| المعلمة | الوصف | القيمة الموصى بها | أساس التحسين |
|---|---|---|---|
| innodb_buffer_pool_size | حجم مخزن التخزين المؤقت لـ InnoDB | 60%–80% من الذاكرة الفعلية | يقوم بتخزين صفحات البيانات وصفحات الفهرس مؤقتًا لتقليل عمليات الإدخال/الإخراج على القرص |
| innodb_log_file_size | حجم ملف سجل الإعادة الفردي | 256M–1G | الحجم الصغير جدًّا يؤدي إلى تكرار نقاط الفحص |
| max_connections | الحد الأقصى لعدد الاتصالات المتزامنة | 200–500 | إذا كان الرقم مرتفعًا جدًّا، فسيؤدي ذلك إلى إهدار الذاكرة؛ وإذا كان منخفضًا جدًّا، فسيؤدي ذلك إلى رفض الاتصالات |
| innodb_flush_method | طريقة التفريغ | O_DIRECT | تتجاوز التخزين المؤقت لنظام التشغيل لتجنب التخزين المؤقت المزدوج |
| sync_binlog | تواتر مزامنة سجل الثنائي | 1 (الأمان) / 100 (الأداء) | الرقم 1 يعني المزامنة عند كل عملية تثبيت؛ وهذا هو الخيار الأكثر أمانًا |
| innodb_io_capacity | سعة الإدخال/الإخراج لـ InnoDB | SSD: 2000 / HDD: 200 | تؤثر على سرعة مسح الصفحات غير النظيفة في الخلفية |
| query_cache_type | تبديل ذاكرة التخزين المؤقت للاستعلامات | OFF | أُزيلت في MySQL 8.0؛ يُوصى بتعطيلها في الإصدار 5.7 |
(2) الضبط الديناميكي للمعلمات
يمكن تعديل بعض المعلمات عبر الإنترنت دون الحاجة إلى إعادة تشغيل المثيل.
SET GLOBAL innodb_buffer_pool_size = 8589934592;
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
▶ مثال: التحقق من معدل نجاح الوصول إلى مخزن المؤقت لـ InnoDB الحالي
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
+---------------------------------------+-----------+
| Variable_name | Value |
+---------------------------------------+-----------+
| Innodb_buffer_pool_read_requests | 1024000 |
| Innodb_buffer_pool_reads | 512 |
+---------------------------------------+-----------+
معدل النجاح = 1 - (512 / 1024000) ≈ 99.95٪؛ حجم مخزن التخزين المؤقت مناسب.
9. مقدمة عن مخطط الأداء
«Performance Schema» هو محرك مراقبة الأداء المدمج في MySQL، والذي يوفر بيانات تشخيصية أكثر تفصيلاً مقارنة بسجل الاستعلامات البطيئة.
(1) تمكين مخطط الأداء
SHOW VARIABLES LIKE 'performance_schema';
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%statement/%';
(2) طرق العرض الشائعة للرصد
| عرض النظام | الغرض |
|---|---|
| sys.statements_with_runtimes_in_95th_percentile | الاستعلامات البطيئة في الشريحة المئوية 95 |
| sys.schema_index_statistics | إحصائيات استخدام الفهرس |
| sys.memory_by_host_by_current_bytes | استخدام الذاكرة لكل اتصال |
| sys.io_by_thread_by_latency | توزيع زمن انتقال الإدخال/الإخراج |
▶ مثال: عرض الفهارس غير المستخدمة
SELECT object_schema, object_name, index_name
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE index_name IS NOT NULL
AND count_star = 0
AND object_schema = 'ecommerce'
ORDER BY object_name;
تؤدي الفهارس غير المستخدمة إلى إهدار مساحة التخزين وتتطلب صيانة إضافية أثناء عمليات INSERT وUPDATE؛ لذا يجب إزالتها على الفور.
10. تمرين عملي شامل: عملية تشخيص الأداء الكاملة
باستخدام منصة التجارة الإلكترونية الخاصة بـ«أليس» كمثال، سنوضح العملية الكاملة بدءًا من تحديد الاستعلامات البطيئة وصولاً إلى التحقق من تحسينات الأداء.
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
mysqldumpslow -s t -t 5 /var/lib/mysql/slow.log
Count: 328 Time=4.52s Rows=1.0 Rows_examined=890000
SELECT * FROM orders WHERE YEAR(create_time)=2025 AND status='PAID';
EXPLAIN SELECT * FROM orders
WHERE YEAR(create_time) = 2025 AND status = 'PAID';
type: ALL | key: NULL | rows: 890000 | Extra: Using where
سبب فشل الفهرسة: تم استخدام الدالة YEAR() على create_time. الحل:
ALTER TABLE orders ADD INDEX idx_status_time (status, create_time);
SELECT order_id, user_id, total_amount
FROM orders
WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'
AND status = 'PAID';
EXPLAIN SELECT order_id, user_id, total_amount
FROM orders
WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'
AND status = 'PAID';
type: range | key: idx_status_time | rows: 3200 | Extra: Using index condition
انخفض عدد الصفوف التي تم مسحها من 890,000 إلى 3,200، وانخفض وقت الاستعلام من 4.5 ثانية إلى 0.08 ثانية. وأخيرًا، قم بضبط مخزن التخزين المؤقت:
SET GLOBAL innodb_buffer_pool_size = 8589934592;
❓ أسئلة شائعة
long_query_time على 1 ثانية، لا يتم تسجيل سوى الاستعلامات التي تنتهي مدة انتظارها، كما أن العبء الإضافي الناتج عن الكتابة في السجل لا يكاد يذكر. إذا كنت قلقًا بشأن الضغط على عمليات الإدخال/الإخراج (I/O)، فيمكنك إخراج السجل إلى ملف بدلاً من جدول، أو استخدام «Performance Schema» كبديل.rows في EXPLAIN دقيق؟rows هو تقدير يستند إلى الإحصاءات، وليس قيمة دقيقة. بالنسبة للأعمدة التي يتسم توزيع بياناتها بالانحراف، قد يكون التقدير بعيدًا عن القيمة الفعلية بشكل ملحوظ. يمكنك استخدام ANALYZE TABLE لتحديث الإحصاءات وتحسين الدقة.innodb_buffer_pool_size؟innodb_buffer_pool_reads: فالمعدل الذي يقل عن 99% يشير إلى أن حجم مخزن التخزين المؤقت صغير جدًا.sort_buffer_size.sys.schema_unused_indexes للاستعلام عن الفهارس التي لم تُستخدم مطلقًا، أو تحقق من Performance Schema بحثًا عن السجلات التي تكون فيها قيمة العمود count_star في table_io_waits_summary_by_index_usage تساوي 0.📖 ملخص
- يُعد سجل الاستعلامات البطيئة نقطة الانطلاق لتحسين الأداء؛ استخدم
mysqldumpslowأو طرق عرض النظام لتحديد نقاط الاختناق بسرعة. - يتراوح حقل «type» في الأمر EXPLAIN بين «system» و«ALL» بترتيب تنازلي من حيث الجودة؛ والهدف هو الوصول إلى مستوى «ref» على الأقل.
- تحسين الفهرس النقاط الرئيسية: تجنب حالات عدم تطابق الفهارس الناتجة عن الدوال أو التحويلات الضمنية؛ واستفد بشكل جيد من الفهارس الشاملة والبادئة الموجودة في أقصى اليسار من الفهارس المركبة.
- إعادة صياغة الاستعلام: استبدال
SELECT *بأعمدة محددة، واستبدال الاستعلامات الفرعية بـJOIN، واستخدام المؤشرات أو عمليات الربط المؤجلة (lazy joins) للترقيم العميق للصفحات - ضبط الإعدادات:
innodb_buffer_pool_sizeهو المعامل الأكثر أهمية؛ ويجب الحفاظ على معدل الوصول إلى مخزن التخزين المؤقت عند 99% أو أكثر. - مخطط الأداء يوفر مراقبة دقيقة يمكنها تحديد الاستعلامات القصيرة عالية التكرار والفهارس غير المستخدمة التي لا يتم تسجيلها في سجل البطء
📝 تمارين
-
سؤال أساسي (مستوى الصعوبة: ⭐): قم بتفعيل سجل الاستعلامات البطيئة، واضبط الحد الأدنى على 0.5 ثانية، واستخدم
mysqldumpslowلتحديد أهم 5 استعلامات بطيئة من حيث عدد مرات التنفيذ. -
تمرين متقدم (درجة الصعوبة ⭐⭐): بالنسبة لاستعلام يحتوي على
typeمن نوعALL، استخدمEXPLAINلتحليله، ثم أضف الفهارس المناسبة للتحقق من أنtypeقد تمت ترقيته إلى مستوىrefأوrange. -
سؤال التحدي (الصعوبة: ⭐⭐⭐): صمم مخطط فهرسة لجدول «order» الذي يحتوي على مليون صف، باستخدام فهرس شامل لتحسين استعلام
SELECT user_id, status, total_amount FROM orders WHERE user_id = ? AND status = ?، وقارن الاختلافات في الحقولrowsوExtraفي الناتجEXPLAINقبل التحسين وبعده. -
تمرين عملي (مستوى الصعوبة: ⭐⭐⭐): أعد كتابة استعلام SQL بطيء يحتوي على استعلام فرعي باستخدام JOIN، ثم قم بتحسينه باستخدام الفهارس لتقليل وقت الاستعلام من ثوانٍ إلى أقل من 100 مللي ثانية. قم بتوثيق عملية التحسين بأكملها.