ابدأ بخطة الاستعلام، ثم أصلح أكبر تكلفة. استخدم EXPLAIN/ لترى ما تفعله قاعدة البيانات فعليًا، أضف المناسبة، احذف استعلامات ، واختر فقط البيانات التي تحتاجها.
ابدأ بخطة الاستعلام، ثم أصلح أكبر تكلفة. استخدم EXPLAIN/ لترى ما تفعله قاعدة البيانات فعليًا، أضف المناسبة، احذف استعلامات ، واختر فقط البيانات التي تحتاجها.
EXPLAIN ANALYZEEXPLAIN ANALYZE يعرض خطة التنفيذ والتوقيتات الحقيقية. Seq Scan على جدول كبير هو الإشارة الحمراء الكلاسيكية:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;
-- Seq Scan on orders (cost=0.00..18500 rows=120)
-- Filter: (customer_id = 42)
-- rows removed by filter: 999880 ← scanned the whole table!
الفهرس يحول المسح الكامل إلى بحث سريع:
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- Now: Index Scan using idx_orders_customer (cost=0.42..8.5 rows=120)
-- 1,000,000-row scan → ~120-row lookup
للفهارس تكلفة على عمليات الكتابة: كل INSERT/UPDATE يجب أن يحدّث الفهرس أيضًا، لذا فهرّس الأعمدة التي تقوم بتصفيتها/الانضمام إليها/الفرز عليها — وليس كل عمود. فهرس مركب مثل (customer_id, created_at) يخدم WHERE customer_id = ? ORDER BY created_at في بنية واحدة.
مشكلة N+1 — استعلام واحد لقائمة، ثم واحد لكل صف — هي من أهم أسباب البطء. استبدلها بالتحميل الفوري أو JOIN أو IN (...) المجمّع:
-- N+1: 1 + 100 queries
SELECT * FROM orders; -- then per order: SELECT * FROM users WHERE id = ?
-- Fixed: one JOIN, only needed columns
SELECT o.id, o.total, u.name
FROM orders o JOIN users u ON u.id = o.user_id;
كذلك اختر فقط الأعمدة المطلوبة (تجنب SELECT *) وصفحّ باستخدام LIMIT/keyset pagination حتى لا تحمّل أبدًا ملايين الصفوف.
قاعدة البيانات هي الاختناق الأكثر شيوعًا. قراءة الخطة تخبرك لماذا يكون الاستعلام بطيئًا بدلاً من التخمين؛ الفهرس الصحيح وإزالة N+1 وتقليص مجموعة النتائج يحوّلان روتينيًا الاستعلامات التي تستغرق ثوانٍ إلى استعلامات بأجزاء من الثانية — دون توسيع الأجهزة.