حول المحتوى:
كيفية استخدام الفهارس، تحليل الاستعلامات، ضبط الإعدادات الأساسية، وإدارة العمليات الثقيلة لتحسين سرعة قواعد PostgreSQL.
في مشاريع الويب والخدمات السحابية الحديثة، أداء قاعدة البيانات PostgreSQL يمكن أن يكون الفرق بين تطبيق سريع يستجيب في أجزاء من الثانية، وتطبيق بطيء يسبب إحباط المستخدمين. في هذا المقال من افهم صح سنشرح بشكل عملي كيفية تحسين PostgreSQL للمطورين عبر أربع ركائز أساسية:
قبل أن نبدأ، إذا لم تكن لديك خلفية كافية عن الفهرسة بشكل عام، يمكنك الرجوع إلى مقالنا: الفهرسة في قواعد البينات و أهميتها، ثم العودة لاستكمال هذا الدليل التطبيقي.
الخطوة الأولى في تحسين أداء أي قاعدة بيانات هي التأكد من أن الاستعلامات الحرجة تستخدم فهارس مناسبة. PostgreSQL يدعم عدة أنواع من الفهارس، واختيارك الصحيح يمكن أن يقدم فرقًا كبيرًا في الأداء.
فكر في إضافة فهرس في الحالات التالية:
مثال بسيط لإنشاء فهرس:
CREATE INDEX idx_users_email ON users (email);
بعد إنشاء هذا الفهرس، أي استعلام مثل:
SELECT * FROM users WHERE email = '[email protected]';
سيتم تنفيذه غالبًا بشكل أسرع بكثير، خصوصًا إذا كان الجدول كبيرًا.
PostgreSQL يدعم خوارزميات فهرسة متعددة، وأشهرها:
إذا أردت التعمق أكثر في خوارزميات الفهرسة نفسها، راجع: أهم خوارزميات الفهرسة المستخدمة في قواعد البيانات.
بدلاً من فهرسة كامل الجدول، يمكنك فهرسة جزء من الصفوف بناءً على شرط. هذا يقلل حجم الفهرس، ويحسن الأداء خاصة في الجداول الضخمة.
مثال: لديك جدول طلبات، ومعظم الاستعلامات تركز على الطلبات النشطة فقط:
CREATE INDEX idx_orders_active
ON orders (user_id)
WHERE status = 'active';
بهذه الطريقة لا يتحمل PostgreSQL تكلفة فهرسة الطلبات القديمة أو المغلقة، ومع ذلك الاستعلامات على الطلبات النشطة تصبح أسرع.
إذا كنت تستخدم أكثر من عمود في الشرط دائمًا، قد تحتاج إلى فهرس مركب:
CREATE INDEX idx_users_country_city ON users (country, city);
مهم: PostgreSQL يستفيد من ترتيب الأعمدة في الفهرس. فهرس (country, city) يساعد في:
WHERE country = 'EG'WHERE country = 'EG' AND city = 'Cairo' لكنه غالبًا لن يساعد كثيرًا في استعلام يعتمد فقط على city بدون country.
كل فهرس تضيفه يعني:
لذلك:
لا يمكنك تحسين PostgreSQL دون فهم كيف ينفذ محرك قاعدة البيانات الاستعلامات. هنا تأتي أهمية EXPLAIN.
إذا كان لديك استعلام بطيء، نفذ:
EXPLAIN SELECT * FROM users WHERE email = '[email protected]';
سيظهر لك خطة التنفيذ (Execution Plan) وما إذا كان يستخدم فهرسًا أو يجري فحصًا كاملاً للجدول (Seq Scan).
EXPLAIN ANALYZE ينفذ الاستعلام فعليًا ويعرض الأرقام الحقيقية للوقت وعدد الصفوف:
EXPLAIN ANALYZE SELECT * FROM users WHERE email = '[email protected]';
ستحصل على بيانات مثل:
إذا كانت تقديرات PostgreSQL مختلفة جدًا عن الواقع، قد تحتاج إلى:
ANALYZE أو تفعيل AUTOVACUUM بشكل مناسب.IN إلى JOIN أو العكس) تغير خطة التنفيذ وتحسن الأداء.إذا كنت تستخدم Django مثلًا، يمكنك الاطلاع على: تحسين استعلامات Django ORM لأداء أعلى لفهم تأثير ORM على أداء PostgreSQL.
الإعدادات الافتراضية لـ PostgreSQL غالبًا لا تكون مهيأة لأجهزة الخوادم القوية، خاصة في الاستضافات السحابية. تعديل بعض الإعدادات في postgresql.conf يمكن أن يعطيك دفعة أداء كبيرة.
هذا الإعداد يحدد حجم الذاكرة التي يستخدمها PostgreSQL لتخزين البيانات في الذاكرة (Cache). قاعدة عامة:
مثال: إذا كانت لديك 8GB RAM:
shared_buffers = 2GB
work_mem هي الذاكرة المخصصة لكل عملية فرز (Sort) أو Hash في الاستعلام. إذا كانت صغيرة جدًا، سيستخدم PostgreSQL القرص، مما يبطئ الاستعلامات التي تعتمد على ORDER BY أو GROUP BY.
يمكنك تعيين قيمة عامة متوسطة، مثلاً:
work_mem = 16MB أو 32MB حسب حجم الخادم.
لكن انتبه: هذه الذاكرة لكل عملية وليس لكل اتصال فقط، لذلك لا ترفعها بشكل مبالغ فيه إذا كان عندك عدد اتصالات ضخم.
يستخدم أثناء عمليات الصيانة مثل VACUUM و CREATE INDEX. قيمته الأعلى تساعد في تسريع هذه العمليات:
maintenance_work_mem = 256MB أو أكثر على الخوادم الكبيرة.
هذا الإعداد لا يحجز ذاكرة فعليًا، لكنه يخبر PostgreSQL بكمية الذاكرة المتاحة للكاش بشكل عام (RAM + نظام التشغيل). هذا يساعد المحرك في اختيار خطط تنفيذ أفضل.
غالبًا يتم ضبطه على:
effective_cache_size = 50% - 75% من RAM
تذكر أن أي تعديل على إعدادات PostgreSQL يحتاج غالبًا إلى إعادة تشغيل الخدمة، لذا اختبر التغييرات في بيئة تجريبية قبل بيئة الإنتاج.
أداء PostgreSQL لا يعتمد فقط على الاستعلام الفردي، بل على كيفية توزيع الحمل على الخادم. العمليات الثقيلة مثل توليد تقارير ضخمة أو استيراد بيانات كبيرة قد تؤثر على سرعة باقي الاستعلامات.
لا تجعل طلب HTTP ينتظر استعلام ثقيل يستغرق دقائق. بدلاً من ذلك:
استعلامات مثل:
SELECT * FROM logs;
بدون LIMIT يمكن أن تكون كارثية في الجداول الكبيرة. الأفضل دائمًا:
LIMIT 50 OFFSET 0.الاستعلامات التي تقوم بتحديث عدد كبير من الصفوف قد تحجز Locks وتمنع استعلامات أخرى من التنفيذ بشكل سلس. لتقليل المشاكل:
pg_locks إذا كنت تشك في وجود تعارضات.PostgreSQL لا يحذف الصفوف بشكل فعلي عند تنفيذ DELETE أو UPDATE، بل يعلمها كمحذوفة (Dead Tuples) ويحتاج إلى عملية VACUUM لتنظيفها.
تأكد من:
VACUUM (FULL) في أوقات قلة الحمل إذا كان هناك تضخم كبير في الجداول.تحسين PostgreSQL لا يقتصر على إعدادات الخادم، بل يرتبط كذلك بكيفية كتابة الكود في التطبيق.
المشكلة المعروفة N+1 تحدث عندما يقوم التطبيق باستعلام رئيسي، ثم استعلام إضافي لكل صف نتيجة. هذا يؤدي لمئات أو آلاف الاستعلامات الصغيرة بدلًا من استعلامات قليلة محسنة.
المنطق نفسه الذي يطبق على تحسين كود بايثون أو أي لغة ينطبق هنا: تقليل التعقيد، تقليل الطلبات غير الضرورية، الاستفادة من الكاش. يمكنك مراجعة: كيف يمكن تحسين أداء وسرعة تنفيذ كود البايثون لمزيد من أفكار تحسين الكود بشكل عام، ثم إسقاطها على التعامل مع قاعدة البيانات.
مثال مختصر لإنشاء Materialized View:
CREATE MATERIALIZED VIEW active_users_stats AS
SELECT country, count(*) AS users_count
FROM users
WHERE status = 'active'
GROUP BY country;
ثم تحديثها:
REFRESH MATERIALIZED VIEW active_users_stats;
تحسين PostgreSQL ليس خطوة واحدة وتنتهي، بل عملية مستمرة. بعض النصائح العملية:
لتلخيص ما سبق، إذا أردت خطة عملية لتحسين أداء PostgreSQL في مشروعك:
باتباع هذه الخطوات ستتمكن من تحقيق تحسين PostgreSQL بشكل ملموس، وتقليل أوقات استجابة التطبيق، واستغلال موارد الخادم بكفاءة أعلى، سواء كنت تعمل على استضافة مشتركة بسيطة أو بنية تحتية سحابية معقدة.
كيفية استخدام الفهارس، تحليل الاستعلامات، ضبط الإعدادات الأساسية، وإدارة العمليات الثقيلة لتحسين سرعة قواعد PostgreSQL.
مساحة اعلانية