لو SELECT بسيط على جدول 1.2 مليون صف بياخد 8.4 ثانية وأنت متأكد إن السيرفر قوي، المشكلة مش في الـ RAM ولا الـ CPU. المشكلة إن قاعدة البيانات بتقلّب الجدول صف صف زي حد بيبص في 1.2 مليون ورقة بإيده. الـ Index بسطر SQL واحد بينزّل الزمن لـ 5 مللي ثانية، 1690 ضعف أسرع.
هذا المقال للمستوى: مبتدئ
Database Indexes: من 8 ثواني لـ 5 مللي ثانية بدون لمس السيرفر
المشكلة باختصار
عندك جدول users فيه 1.2 مليون مستخدم، وعملت أبسط استعلام ممكن:
SELECT * FROM users WHERE email = 'ahmed@example.com';الاستعلام بياخد 8.4 ثانية على PostgreSQL 16 على لابتوب 16GB رام و SSD سريع. السبب مش حجم البيانات. السبب إن الـ DB بتعمل عملية اسمها Sequential Scan: بتقرا الجدول من أوله لآخره، صف صف، وبتقارن كل email حتى تلاقي اللي محتاجاه. لو السطر اللي بتدوّر عليه في آخر الجدول، لازم تقرا 1.2 مليون صف كاملة قبل ما تلاقيه.
المثال البسيط: قاموس المدرسة
تخيّل إنك بتدوّر على كلمة "احترام" في قاموس فيه 50,000 كلمة، لكن الكلمات مش مرتّبة أبجدياً، متناثرة بشكل عشوائي. هتقعد تقلّب صفحة صفحة لمدة ساعة ونصف. ده بدون Index.
دلوقتي تخيّل نفس القاموس بس الكلمات مرتّبة أبجدياً. بتفتح في النص، تشوف "م" يبقى لازم ترجع لورا. تفتح في الربع الأول، تشوف "ا"، تكمّل في "اح"، بعدين "احت"، وفي خلال 15 ثانية بتلاقي الكلمة. ده الـ Index.
الـ Index في قاعدة البيانات هو نفس الفكرة: هيكل بيانات منفصل عن الجدول، فيه قيم العمود اللي اخترته (مثلاً email) مرتّبة، وكل قيمة معاها مؤشّر (pointer) للسطر الأصلي في الجدول. الـ DB بتدوّر في الـ Index، تلاقي القيمة، تجيب المؤشّر، وتروح للسطر مباشرةً.
التعريف العلمي بدقة
الـ Index الافتراضي في PostgreSQL نوعه B-tree (شجرة متوازنة بـ branching factor عالي). الشجرة دي مكوّنة من عقد، كل عقدة فيها مجموعة قيم مرتّبة + مؤشّرات للعقد الفرعية. الفايدة الرياضية: للبحث عن قيمة، بتنزل من الجذر للأوراق في log₂(N) خطوة بدل N.
الفرق رياضي بحت، مش متعلق بنوع السيرفر:
- Sequential Scan على 1.2M صف = 1,200,000 مقارنة في أسوأ حالة.
- B-tree lookup على 1.2M صف = log₂(1,200,000) ≈ 21 مقارنة فقط.
الفرق النظري ~57,000 ضعف. الفرق العملي أقل (1,690x في الاختبار) بسبب overhead القراءة من القرص و cache hits، لكن المبدأ نفسه.
الكود الكامل قابل للنسخ
على PostgreSQL 16، خطوة بخطوة: