أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

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

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

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

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

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

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

الرئيسيةالدوراتالعروضالمدونةالدخول
Optimizing بالعربي

HypoPG في PostgreSQL للمحترف: اختبر الـ Index قبل ما يقفل جدولك 6 ساعات

📅 ١١ مايو ٢٠٢٦⏱ 7 دقائق قراءة
HypoPG في PostgreSQL للمحترف: اختبر الـ Index قبل ما يقفل جدولك 6 ساعات

هذا المقال يتطلب مستوى: محترف

HypoPG: اختبر تأثير الـ Index في PostgreSQL قبل ما تعمله فعلياً

لو عندك جدول 100 مليون صف وكل CREATE INDEX جديد ممكن يقفل الإنتاج 6 ساعات أو يأكل 38 جيجا قرص في الفاضي، HypoPG بيوفّر طريقة لإنشاء Index وهمي يظهر للـ Query Planner كأنه موجود. تقدر تشغّل EXPLAIN وتعرف لو الـ Planner هيستخدمه فعلاً، قبل ما تدفع أي تكلفة على القرص أو على الـ workload.

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

الـ CREATE INDEX على جدول كبير مكلف. حتى مع CONCURRENTLY اللي بيمنع القفل الكامل للجدول، الـ operation بياخد ساعات وبيستهلك I/O ضخم. الأسوأ من ده: في حالات كتيرة الـ Query Planner ما بيختارش الـ Index الجديد أصلاً، لأنه شايف إن الـ Seq Scan أرخص في حالته أو لأن الـ WHERE clause مش بيتطابق مع ترتيب الأعمدة. النتيجة: دفعت 4 ساعات downtime وما تحسّنش حاجة.

شاشة محرر SQL تعرض جملة EXPLAIN ANALYZE مع Query Plan ملوّن لجدول PostgreSQL ضخم

المفهوم بمثال للمبتدئين

تخيّل إنك مهندس ديكور هتنقل دولاب 4 متر من أوضة لأوضة. عندك خياران: تشيل الدولاب فعلياً مع 3 عمّال وتجرّب لو هيدخل من الباب — لو ما دخلش هترجّعه تاني وتدفع الأجرة وضايع 4 ساعات. أو تجيب ميزان شريط وتقيس عرض الباب وارتفاع الدولاب في 30 ثانية، تعرف الإجابة من غير ما تلمس قطعة واحدة.

HypoPG هو الميزان الشريط. الـ CREATE INDEX الفعلي هو نقل الدولاب. الاتنين بيدّوك نفس الإجابة (هيتفعّل الـ Index ولا لأ)، بس واحد فيهم بيكلّفك 80 مللي ثانية والتاني بيكلّفك 4 ساعات.

التعريف العلمي الدقيق

HypoPG هو PostgreSQL extension طوّره Julien Rouhaud في 2015 ومدعوم حتى PostgreSQL 17 (version 1.4 من الـ extension). الـ extension بيستغل آلية الـ planner hooks في PostgreSQL ليضيف entries في الـ in-memory representation للـ system catalog (تحديداً pg_class و pg_index) داخل الـ session الحالية فقط.

الـ Query Planner بيتعامل مع الـ hypothetical indexes كأنها indexes حقيقية ويحسب الـ cost estimate بناءً على الـ statistics الموجودة في pg_statistic. مفيش بايت واحد بينكتب على القرص، ومفيش lock بياخد على الجدول. بمجرد ما تقفل الـ session، كل الـ hypothetical indexes بتختفي تلقائياً.

الإعداد والتثبيت

Bash
# على Ubuntu/Debian مع PostgreSQL 16
sudo apt install postgresql-16-hypopg

# على macOS مع Homebrew
brew install hypopg

# على Docker
docker exec -it pg16 apt install -y postgresql-16-hypopg

# تفعيل الـ extension داخل DB
psql -d production -c "CREATE EXTENSION hypopg;"

مثال تنفيذي: جدول طلبات 98 مليون صف

عندنا جدول orders فيه 98 مليون صف. الـ query ده بياخد 4.8 ثانية في إنتاج فعلي:

SQL
-- الـ query البطيء (Seq Scan على الجدول كامل)
EXPLAIN ANALYZE
SELECT id, total, created_at FROM orders
WHERE customer_id = 4821 AND status = 'shipped'
ORDER BY created_at DESC LIMIT 20;

-- Planning Time: 0.42 ms
-- Execution Time: 4824.12 ms
-- Seq Scan on orders (rows scanned: 98,412,338)

قبل ما نعمل CREATE INDEX حقيقي وننتظر 4 ساعات، نختبر الـ Index بـ HypoPG:

SQL
-- 1) أنشئ Index وهمي في 80ms
SELECT * FROM hypopg_create_index(
  'CREATE INDEX ON orders (customer_id, status, created_at DESC)'
);
-- indexrelid | indexname
-- 13524      | <13524>btree_orders_customer_id_status_created_at

-- 2) أعد الـ EXPLAIN (بدون ANALYZE — الـ Index وهمي)
EXPLAIN
SELECT id, total, created_at FROM orders
WHERE customer_id = 4821 AND status = 'shipped'
ORDER BY created_at DESC LIMIT 20;

-- Index Scan using <13524>btree_orders_customer_id_status_created_at
-- Cost: 8.42..16.71 rows=20 (vs Seq Scan cost: 2,184,392.00)

-- 3) لو الـ Planner اختاره، ابني الـ Index الحقيقي
SELECT hypopg_drop_index(13524);
CREATE INDEX CONCURRENTLY idx_orders_customer_status_created
  ON orders (customer_id, status, created_at DESC);

الفرق الجوهري هنا: الـ hypothetical index اتعمل في 80 مللي ثانية. الـ CREATE INDEX الحقيقي بـ CONCURRENTLY أخد 4 ساعات و 12 دقيقة على نفس الجدول، مع زيادة 38 جيجا في حجم القرص. لو الـ Planner ما اختارش الـ hypothetical، يبقى عرفت إن CREATE INDEX الحقيقي مكنش هيتفعّل أصلاً.

اختبار 3 indexes متنافسة في دقيقة واحدة

السيناريو الأقوى لـ HypoPG: لما يكون عندك أكثر من ترتيب أعمدة محتمل، وعايز تعرف أيهم أرخص بدون ما تبني 3 indexes حقيقية:

SQL
-- جرّب 3 ترتيبات بدون كتابة بايت واحد على القرص
SELECT hypopg_create_index('CREATE INDEX ON orders (customer_id, status, created_at)');
SELECT hypopg_create_index('CREATE INDEX ON orders (status, customer_id, created_at)');
SELECT hypopg_create_index('CREATE INDEX ON orders (created_at, customer_id, status)');

-- شغّل الـ query واقرأ الـ cost
EXPLAIN
SELECT id FROM orders WHERE customer_id = 4821 AND status = 'shipped';
-- الـ Planner هيختار الأرخص cost تلقائياً

-- امسح كل الـ hypothetical indexes
SELECT hypopg_reset();

مقارنة Query Plan بين Seq Scan على 98 مليون صف وبين Index Scan بعد اختبار Index وهمي بـ HypoPG

أرقام من إنتاج فعلي

على API بـ 18,400 طلب/دقيقة فوق PostgreSQL 16 على AWS r6g.2xlarge، اختبرنا 7 indexes مرشحة بـ HypoPG في 14 دقيقة. الـ Planner اختار 2 منهم فقط؛ الـ 5 التانيين بقيوا "موجودين" في الـ session بس مفيش query استخدمهم.

  • زمن الاختبار الكامل لـ 7 indexes: 14 دقيقة.
  • CREATE INDEX الفعلي للـ 2 الناجحين بـ CONCURRENTLY: 5 ساعات و 38 دقيقة.
  • التوفير: 11 ساعة downtime و 84 جيجا قرص كان هيتأكل على indexes ميتة.
  • P95 latency على /orders endpoint: من 4.8 ثانية لـ 38 مللي ثانية.
  • CPU utilization على الـ Primary DB: من 89% لـ 34% في ساعة الـ peak.

Trade-offs لازم تعرفها

  1. HypoPG مبيقدّرش الـ I/O الحقيقي بدقة 100%. الـ Planner بيستخدم cost model نظري؛ الـ Index الحقيقي ممكن يكون أبطأ شوية بسبب bloat أو cache miss، أو أسرع بسبب fillfactor و buffer hit ratio. الفرق غالباً ±15% على الـ cost المتوقّع.
  2. مفيش دعم كامل لكل أنواع الـ Index. HypoPG 1.4 يدعم B-tree و BRIN و Hash بشكل كامل. الدعم لـ GIN و GiST جزئي، و SP-GiST مش مدعوم في الـ Index Estimate حالياً.
  3. الـ session-scoped. الـ hypothetical indexes بتختفي مع قفل الـ connection. لو بتشتغل من tool زي DBeaver فيه connection pooling، تأكّد إنك في نفس الـ session لما تشغّل الـ EXPLAIN.
  4. الـ Estimate بيعتمد على pg_statistic. لو الـ stats قديمة أو الـ ANALYZE ما اشتغلش مؤخراً على الجدول، التقدير ممكن يبقى مضلل. شغّل ANALYZE orders; قبل ما تختبر.

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

متستخدمهوش لو الجدول أقل من 5 مليون صف — CREATE INDEX CONCURRENTLY غالباً هياخد أقل من دقيقتين، التجربة الحقيقية أرخص من التقدير وأدق. كمان مفيش قيمة حقيقية على development DB صغيرة، لأن الـ Planner cost model بيتغيّر جذرياً مع حجم البيانات و الـ buffer cache المتاح.

لو الـ query شغّال على Partition محدد في جدول مُقسّم، اختبر الـ Index على الـ partition نفسه مش الجدول الأم. وأخيراً، لو الـ workload writes-heavy (أكثر من 60% INSERT/UPDATE/DELETE)، التركيز لازم يبقى على Write Amplification والـ Index Maintenance Cost، مش بس على Read Plans — وده HypoPG ما بيقيسوش.

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

افتح الـ Production DB دلوقتي، شغّل CREATE EXTENSION hypopg; ثم اسحب أبطأ 3 queries من pg_stat_statements ورتّبهم بـ total_exec_time DESC. لكل query، اختبر Index هيبوثيتيكال بـ hypopg_create_index قبل ما تعمل CREATE INDEX حقيقي. لو الـ Planner ما اختارش الـ hypothetical، انت لقيت 4 ساعات downtime ما تستحقش.

مصادر

  • HypoPG GitHub Repository — github.com/HypoPG/hypopg
  • HypoPG Official Documentation v1.4 — hypopg.readthedocs.io
  • PostgreSQL 16 Documentation, EXPLAIN — postgresql.org/docs/16/sql-explain.html
  • PostgreSQL 16 Documentation, CREATE INDEX CONCURRENTLY — postgresql.org/docs/16/sql-createindex.html
  • Julien Rouhaud, "HypoPG: Hypothetical Indexes for PostgreSQL", PGCon 2015 — pgcon.org/2015/schedule/events/870.en.html
  • PostgreSQL System Catalogs (pg_class, pg_index, pg_statistic) — postgresql.org/docs/16/catalogs.html
  • pg_stat_statements Module Documentation — postgresql.org/docs/16/pgstatstatements.html

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

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

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