أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالمناهج والباقات
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
البرمجة بالعربي

ليه الـ Database Index بيخلّي query على مليون صف أسرع 600 مرة

متوسط١٤ يونيو ٢٠٢٦5 دقائق قراءة
ليه الـ Database Index بيخلّي query على مليون صف أسرع 600 مرة

هذا المقال موجّه للمستوى المتوسط: يفترض إنك بتكتب SQL وعملت SELECT … WHERE قبل كده، بس لسه مش فاهم بالظبط ليه إضافة سطر واحد ممكن تقلّب الأداء رأسًا على عقب.

الـ Database Index: ازاي تحوّل query من ثانية لـ نص مللي ثانية

لو عندك جدول فيه مليون مستخدم، وSELECT * FROM users WHERE email = '…' بياخد أكتر من ثانية، المشكلة مش في حجم السيرفر ولا في عدد الـ CPU cores. المشكلة إن قاعدة البيانات بتقرأ المليون صف واحد واحد علشان تلاقي صف واحد. الحل سطر واحد، بس لازم تفهم بيعمل إيه قبل ما تكتبه.

صفوف خوادم في مركز بيانات تمثّل قاعدة بيانات بمليون صف يبحث فيها الـ index

المشكلة باختصار

بدون index، أي بحث بشرط WHERE بيتحوّل لـ Sequential Scan: القاعدة بتمر على كل صف في الجدول وتقارن. ده معناه إن وقت البحث بيكبر خطيًا مع حجم الجدول. ألف صف سريع، مليون صف بطيء، مية مليون صف كارثة. ومع كل مستخدم جديد بيدخل النظام، الـ query بيبقى أبطأ من غير ما تغيّر سطر واحد في كودك.

الفكرة الأساسية بمثال بسيط

تخيّل كتاب 1000 صفحة وعايز تلاقي كلمة "Transaction". عندك طريقتين. الأولى: تفتح من أول صفحة وتقرا كلمة كلمة لحد ما تلاقيها — ده الـ Sequential Scan. الثانية: تروح للفهرس في آخر الكتاب، الكلمات مترتبة أبجديًا، تلاقي "Transaction" في ثانية وجنبها رقم الصفحة 418، تفتح على طول. ده بالظبط اللي بيعمله الـ index.

الفهرس نفسه مش الكتاب، هو نسخة صغيرة مرتبة من كلمة واحدة (العمود) + إشارة لمكان الصف الأصلي. علشان كده الـ index بياخد مساحة زيادة على الديسك، لكنه بيوفّر إنك متقراش الكتاب كله.

رفوف كتب في مكتبة ترمز لفهرس الكتاب الذي يشبه فكرة الـ B-Tree index في قواعد البيانات

التعريف العلمي: ليه B-Tree تحديدًا

أغلب قواعد البيانات (PostgreSQL، MySQL/InnoDB) بتخزّن الـ index في هيكل اسمه B-Tree، اتعرّف أول مرة في ورقة Rudolf Bayer و Edward McCreight سنة 1972. الـ B-Tree شجرة متوازنة (balanced): كل المسارات من الجذر للورقة ليها نفس الطول تقريبًا. ده بيخلّي البحث بتكلفة O(log n) بدل O(n).

الفرق مش تجميلي. في O(n) مليون صف = مليون خطوة. في O(log n) بقاعدة فروع كبيرة، مليون صف = حوالي 3 إلى 4 قفزات للوصول للصف. ده مصدر التحسّن: مش إن القاعدة بقت أسرع، لكن عدد الخطوات نزل من مليون لأربعة.

مثال تنفيذي على PostgreSQL

جرّب ده بنفسك على جدول فيه مليون صف. استخدم EXPLAIN ANALYZE علشان تشوف الفرق بأرقام حقيقية مش تخمين:

SQL
-- جدول مستخدمين
CREATE TABLE users (
  id         BIGSERIAL PRIMARY KEY,
  email      TEXT NOT NULL,
  city       TEXT,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- عبّيه بمليون صف للاختبار
INSERT INTO users (email, city)
SELECT 'user' || g || '@example.com',
       (ARRAY['Cairo','Giza','Alex'])[1 + (g % 3)]
FROM generate_series(1, 1000000) AS g;

-- (1) بحث قبل الـ index
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'user777777@example.com';
-- Seq Scan on users ... actual time=312.4 ms

-- (2) ضيف الـ index (السطر الواحد بتاعنا)
CREATE INDEX idx_users_email ON users (email);

-- (3) نفس البحث بعد الـ index
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'user777777@example.com';
-- Index Scan using idx_users_email ... actual time=0.5 ms

على إعداد PostgreSQL 16 عادي، النتيجة المقاسة نزلت من حوالي 312 مللي ثانية لـ 0.5 مللي ثانية — أسرع بحوالي 600 مرة. الرقم بيتغيّر حسب جهازك وإعداداتك، لكن رتبة الفرق (مئات الأضعاف) ثابتة. لاحظ كلمة Seq Scan في الخطة الأولى وIndex Scan في التانية — دي أول حاجة تدوّر عليها في EXPLAIN ANALYZE.

سيناريو واقعي

افترض إن عندك متجر بـ 50 ألف طلب/يوم، وصفحة "طلباتي" بتعمل WHERE user_id = ? على جدول طلبات فيه 8 ملايين صف. بدون index على user_id، كل فتح للصفحة بيعمل Seq Scan على 8 ملايين صف. في ساعة الذروة، عشرات الـ Seq Scans بالتوازي بياكلوا الـ CPU ويوقّعوا زمن الاستجابة لكل المستخدمين، مش بس صاحب الصفحة. index واحد على user_id بيحوّل ده لـ Index Scan على آلاف الصفوف فقط.

الـ Trade-offs — مفيش حاجة ببلاش

  • مساحة ديسك: الـ index بياخد مساحة إضافية (ممكن 10–30% من حجم الجدول لكل index). بتكسب سرعة قراءة، بتخسر تخزين.
  • كتابة أبطأ: كل INSERT و UPDATE و DELETE لازم يحدّث الـ index كمان. الافتراض هنا إن جدولك بيتقري أكتر مما بيتكتب — وده صحيح لأغلب التطبيقات، بس مش كلها.
  • صيانة: الـ B-Tree ممكن يتفكّك (fragmentation) مع التعديلات الكتيرة ويحتاج REINDEX أحيانًا.
  • أعمدة منخفضة التنوّع: index على عمود قيمه قليلة (زي is_active بقيمتين بس) غالبًا مش بيفيد، لأن نص الجدول هيرجع بأي حال.

متى لا تستخدم index

متحطّش index لو الجدول صغير (آلاف الصفوف القليلة) — الـ Seq Scan هيبقى أسرع أصلًا. متحطّش index على عمود نادرًا ما بتفلتر بيه، لأنك بتدفع تكلفة الكتابة من غير مكسب قراءة. ومتحطّش index على جدول كتابة-مكثّفة (logs/events) إلا للأعمدة اللي بتبحث بيها فعلًا، عشان متبطّئش الـ ingestion. القاعدة: index الأعمدة اللي بتظهر في WHERE و JOIN و ORDER BY على الجداول الكبيرة، مش كل عمود.

الخطوة التالية

افتح أبطأ query عندك دلوقتي وشغّل قبله EXPLAIN ANALYZE. لو شفت Seq Scan على جدول كبير مع شرط WHERE على عمود معيّن، ضيف index على العمود ده وأعد القياس. لو الزمن نزل لرتبة المللي ثانية، كنت بتدفع ضريبة بحث خطّي من غير داعي.

المصادر

  • R. Bayer, E. McCreight, "Organization and Maintenance of Large Ordered Indexes", Acta Informatica, 1972 — الورقة الأصلية للـ B-Tree.
  • PostgreSQL Documentation — Chapter 11 "Indexes" و Chapter 14 "Using EXPLAIN".
  • Markus Winand, "Use The Index, Luke" (use-the-index-luke.com) — مرجع عملي لفهم B-Tree والأداء.
  • MySQL Reference Manual — "How MySQL Uses Indexes" و InnoDB B-Tree indexes.
  • CMU 15-445 Database Systems — محاضرات Tree Indexes (B+Tree).

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة