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

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

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

المنصة

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

الدعم

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

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

الرئيسيةالدوراتالمناهجالمدونةالدخول
الأوتوميشن

راقب أبطأ استعلامات PostgreSQL: تقرير أسبوعي تلقائي على Slack

متوسط18 يوليو 20265 دقائق قراءة
راقب أبطأ استعلامات PostgreSQL: تقرير أسبوعي تلقائي على Slack

المستوى: متوسط

لو عندك قاعدة PostgreSQL في الإنتاج وبتكتشف الاستعلام البطيء بس لمّا العميل يشتكي، يبقى انت متأخّر أسبوع. التقرير اللي هنبنيه هنا بيوصّلك أبطأ 10 استعلامات كل يوم إثنين الصبح على Slack، من غير ما تفتح السيرفر ولا تدفع لأداة مراقبة.

راقب أبطأ استعلامات PostgreSQL: تقرير أسبوعي تلقائي على Slack

الفكرة بسيطة. امتداد pg_stat_statements بيسجّل إحصائيات كل استعلام، وسكربت واحد مع cron بيلخّص أبطأها ويبعتها. النتيجة: بدل ما تخمّن، بتشوف رقم واضح كل أسبوع.

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

الصفحة بتحس بطيئة أحيانًا، والـ CPU مرتاح. مفيش حد يعرف أنهي استعلام هو السبب بالظبط. فبتضيف فهارس عشوائية وتتمنى. ده تخمين، مش هندسة. اللي ناقصك مش سيرفر أقوى، اللي ناقصك رؤية.

إيه هو pg_stat_statements؟ (المثال الأول، التعريف بعده)

تخيّل فاتورة موبايل مفصّلة. الفاتورة مش بتقولك "اتصلت 400 مرة" وخلاص. بتجمّع المكالمات المتشابهة وتقولك: مكالمات الدعم كلّفتك كذا، والمكالمات الدولية كلّفتك كذا. فتعرف في ثانية مين بيسحب فلوسك فعلًا.

الامتداد بيعمل نفس الحاجة بالظبط مع استعلاماتك. بياخد كل استعلام، يشيل القيم المتغيّرة منه (بيحوّل id = 42 إلى id = $1)، ويجمّع كل الاستعلامات المتشابهة في صف واحد. الصف بيحمل عدد المرات calls، وإجمالي وقت التنفيذ total_exec_time، ومتوسط الوقت mean_exec_time. التعريف الدقيق إذًا: جدول إحصائي حيّ لكل نمط استعلام مرّ على قاعدتك منذ آخر تصفير.

الخدعة اللي بتفرق: رتّب بإجمالي الوقت مش بالمتوسط

ركز في النقطة دي. استعلام بياخد 40 مللي ثانية بس بيتنفّذ 900 ألف مرة في الأسبوع يساوي 36 ألف ثانية إجمالي، يعني 10 ساعات معالجة. استعلام تاني بياخد 1.4 ثانية لكنه بيتنفّذ 2000 مرة بس يساوي 2800 ثانية. البطيء "بالإحساس" هو التاني، لكن اللي بياكل سيرفرك فعلًا هو الأول.

الطريقة الشائعة إنك ترتّب بالمتوسط، وهي بتفشل هنا لأنها بتخبّي الاستعلام الصغير كثير التكرار. رتّب بإجمالي وقت التنفيذ عشان تشوف التكلفة الحقيقية.

خطوة 1: فعّل الامتداد

SQL
# في ملف postgresql.conf
shared_preload_libraries = 'pg_stat_statements'

-- بعد إعادة تشغيل السيرفر مرة واحدة، ونفّذ داخل قاعدتك:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

الامتداد جزء من حزمة contrib الرسمية، ومدعوم على Amazon RDS و Google Cloud SQL. محتاج إعادة تشغيل واحدة للسيرفر بعد تعديل shared_preload_libraries، فخطّطها في نافذة صيانة.

خطوة 2: الاستعلام الأساسي

SQL
SELECT
  round(total_exec_time::numeric / 1000, 1) AS total_s,
  calls,
  round(mean_exec_time::numeric, 1)        AS mean_ms,
  substr(query, 1, 80)                     AS q
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

القسمة على 1000 بتحوّل المللي ثانية لثواني عشان الأرقام تبقى مقروءة في التقرير. الترتيب بـ total_exec_time DESC هو قلب الحكاية.

شاشة تعرض كود SQL في محرر يمثل كتابة استعلامات قاعدة البيانات وضبط الفهارس

خطوة 3: السكربت اللي بيبعت على Slack

Bash
#!/usr/bin/env bash
set -euo pipefail

SLACK_WEBHOOK="https://hooks.slack.com/services/XXX/YYY/ZZZ"
PGURL="postgresql://readonly@db.internal:5432/app"

ROWS=$(psql "$PGURL" -At -F '|' <<'SQL'
SELECT round(total_exec_time::numeric/1000, 1) AS total_s,
       calls,
       round(mean_exec_time::numeric, 1)       AS mean_ms,
       substr(regexp_replace(query, '\s+', ' ', 'g'), 1, 90) AS q
FROM pg_stat_statements
WHERE query NOT LIKE '%pg_stat_statements%'
ORDER BY total_exec_time DESC
LIMIT 10;
SQL
)

MSG='*أبطأ 10 استعلامات — آخر 7 أيام*'$'\n''```'$'\n'
while IFS='|' read -r total_s calls mean_ms q; do
  MSG+="${total_s}s  x${calls}  ~${mean_ms}ms  ${q}"$'\n'
done <<< "$ROWS"
MSG+='```'

curl -sS -X POST -H 'Content-type: application/json' \
  --data "$(jq -n --arg t "$MSG" '{text:$t}')" "$SLACK_WEBHOOK"

# صفّر العدادات لبدء نافذة أسبوع جديدة
psql "$PGURL" -c "SELECT pg_stat_statements_reset();"

Slack Incoming Webhook بيديك رابطًا، وأي طلب POST بـ JSON فيه حقل text بيظهر كرسالة في القناة. أداة jq بتبني الـ JSON بأمان بدل ما تركّب النص بإيدك وتكسره أول ما استعلام يحتوي علامة اقتباس.

خطوة 4: شغّلها كل إثنين الصبح

Bash
0 8 * * 1  /opt/scripts/slow-query-digest.sh >> /var/log/slow-digest.log 2>&1

السطر ده معناه: الساعة 8 صباحًا كل يوم إثنين. آخر أمر في السكربت بيصفّر العدادات، فكل تقرير بيغطّي أسبوعًا نضيفًا لوحده.

الأرقام و trade-offs

الافتراض هنا إن عندك PostgreSQL 13 أو أحدث، لأن الأعمدة اتسمّت total_exec_time وmean_exec_time من الإصدار ده؛ قبله كان الاسم total_time. التكلفة الحقيقية: الامتداد بيضيف حِملًا بسيطًا على كل استعلام، والتوثيق الرسمي بيوصفه بأنه منخفض لكنه مش صفر. وبيتتبّع افتراضيًا 5000 نمط استعلام عبر إعداد pg_stat_statements.max. المكسب: رؤية أسبوعية بصفر تكلفة أدوات. الثمن: تصفير العدادات بيمسح التاريخ، فلو عايز تقارن أسبوعًا بأسبوع، خزّن ناتج الاستعلام في جدول قبل استدعاء pg_stat_statements_reset().

متى لا تستخدم هذه الطريقة

لو عندك أداة APM زي Datadog أو pganalyze بترصد الاستعلامات أصلًا، التقرير ده تكرار لشغل موجود. ولو قاعدتك صغيرة وترافيكها خفيف، مش هتلاقي فيها استعلامًا يستاهل التعب. ولو مضيفك بيمنع تفعيل الامتدادات — نادر، لكنه موجود في بعض الخدمات المُدارة المقيّدة — فالطريقة دي مش ليك، ولازم تعتمد على سجلّ الاستعلامات البطيئة log_min_duration_statement بدلها.

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

فعّل الامتداد على قاعدة الـ staging دلوقتي، شغّل استعلام الترتيب مرة واحدة يدويًا، وبُص على أول صف. لو لقيت استعلامًا بإجمالي وقت عالٍ وعدد مرات كبير، ده أول فهرس تضيفه الأسبوع ده. قِس الرقم، ضيف الفهرس، وقارن بعد أسبوع. لو الإجمالي نزل، انت في الطريق الصح.

المصادر

  • توثيق PostgreSQL الرسمي — pg_stat_statements (الأعمدة، pg_stat_statements.max، وحِمل التتبّع): postgresql.org/docs/current/pgstatstatements.html
  • Slack — إرسال الرسائل عبر Incoming Webhooks: api.slack.com/messaging/webhooks
  • صيغة crontab من صفحات دليل Linux: man7.org/linux/man-pages/man5/crontab.5.html
  • توثيق PostgreSQL — log_min_duration_statement كبديل عند منع الامتدادات: postgresql.org/docs/current/runtime-config-logging.html

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

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

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