آپ کی رپورٹ ڈیٹابیس ہوسٹ پر تقریباً ایک سیکنڈ میں اور VPN کے ذریعے چار میں مکمل ہوتی ہے، اور psql جو تعداد چھاپتا ہے وہ سیدھا ڈیٹابیس کی طرف اشارہ کرتی ہے۔ وہ تعداد کلائنٹ کی طرف کی سٹاپ واچ ہے، سرور کی پیمائش نہیں۔ یہ بیان کے باہر جانے کے راستے، جواب کے انتظار اور واپس آنے والی قطاروں کو محیط ہے۔ ان تینوں کو الگ کرنا ہی یہ جاننے کا واحد طریقہ ہے کہ کس طرف کو ایڈجسٹ کرنا ہے۔

psql کا ٹائمر درحقیقت کیا ناپتا ہے

\timing on کلائنٹ کے بیان کو ساکٹ میں لکھنے سے عین پہلے سٹاپ واچ شروع کرتا ہے اور اس نتیجے کی آخری قطار پڑھے جانے پر روکتا ہے۔ سرور کا اپنا عمل اسی ونڈو میں کہیں ہوتا ہے، اور ہر وہ ملی سیکنڈ بھی جو پیکٹ سرنگ میں گزارتے ہیں۔ آؤٹ پٹ میں کوئی چیز انہیں الگ نہیں کرتی۔ EXPLAIN بھی ایک تعداد چھاپتا ہے، لیکن وہ سرور بناتا ہے اور کلائنٹ کے انتظار کو خارج کرتا ہے۔ دو تعداد، دو مختلف سوال۔

ایک سیشن شروع کریں، وقت کی پیمائش آن رکھیں، اور جس بیان کی آپ کو پروا ہے اسے اسی کے اندر سے چلائیں۔ سیشن دوبارہ استعمال کرنے سے کنکشن کی لاگت پہلی پیمائش سے باہر رہتی ہے۔

psql "host=db.internal port=5432 dbname=appdb user=app" \
  -c "\timing on" \
  -c "select count(*) from orders where created_at > now() - interval '1 day';"

تعداد اب بھی نتیجے کی منتقلی شامل رکھتی ہے، جو یہاں آپ کو مطلوب ہے۔ اب یہ وہ کنکشن اور تصدیق کا تبادلہ شامل نہیں کرتی جو نیا کال اضافہ کرتا۔

ایک بیان کا تین راستوں پر موازنہ کریں

وہی بیان Unix ساکٹ، LAN پتے اور VPN ہوسٹ نام کے ذریعے چلائیں اور تینوں کا موازنہ کریں۔ اگر صرف آخری سست ہے تو استفسار متغیر نہیں۔

ہر کال پہلے کنکشن بناتی ہے اور پھر بیان ناپتی ہے، اس لیے کنکشن کی لاگت تعداد سے باہر رہتی ہے جبکہ منتقلی اندر رہتی ہے۔ WHERE شق، قطاروں کی تعداد اور کلائنٹ مشین یکساں رکھیں، ورنہ آپ راستوں کی نہیں بلکہ کام کے بوجھ کا موازنہ کر رہے ہیں۔

psql -h /var/run/postgresql -U app -d appdb -c "\timing on" -c "select count(*) from orders;"
psql -h 10.40.0.12 -U app -d appdb -c "\timing on" -c "select count(*) from orders;"
psql -h db.vpn.internal -U app -d appdb -c "\timing on" -c "select count(*) from orders;"

LAN پر فرق عام طور پر نظرانداز کرنے کے قابل چھوٹا ہوتا ہے؛ VPN کے ذریعے اکثر نہیں۔ تینوں نتائج کی ترتیب بعد میں بتاتی ہے کہ کس انتظار پر حملہ کرنا ہے۔

سست مقامی ساکٹ کا مطلب سرور کا کام یا منصوبہ بندی ہے۔ سست LAN نتیجہ کا مطلب استفسار یا وہ حجم جو یہ حرکت دیتا ہے۔ صرف VPN نتیجے کا سست ہونا تاخیر، MTU یا راستے پر دستیاب بینڈوتھ کا مطلب ہے، اور کوئی انڈیکس تبدیلی اسے درست نہیں کرتی۔

سرور کا اپنا عمل آوری کا وقت نکالیں

سرور بتا سکتا ہے کہ اس نے کتنا وقت صرف کیا، اور کلائنٹ کی تعداد کے سامنے رکھنے والی تعداد وہی ہے۔ ANALYZE کے ساتھ EXPLAIN بیان چلاتا ہے اور منصوبے کے اندر منصوبہ بندی اور عمل آوری کا وقت چھاپتا ہے، جبکہ BUFFERS کیشے کا رویہ جوڑتا ہے جو اکثر گرم دوڑ کو ٹھنڈی کے سامنے بیان کرتا ہے۔ اگر لکھنے کا ارادہ نہ ہو تو اسے تحریری بیانات کی طرف نہ موڑیں۔ صرف پڑھنے والی نقل پر شروع کرنے کی سب سے محفوظ جگہ یہی ہے، اور psql حوالہ ٹائمر کے کلائنٹ طرف کے دائرے کی دستاویز کرتا ہے۔

ان بیانات کے لیے جو ایپلیکیشن پہلے ہی چلاتی ہے، pg_stat_statements کچھ دوبارہ چلائے بغیر سرور طرف کا عمل جمع کرتا ہے۔ قطاریں فی معمول بنائے گئے استفسار ہیں، اس لیے ایک اندراج کئی کال مقامات کو محیط ہو سکتا ہے۔

select calls, round(mean_exec_time::numeric, 2) as mean_ms, rows
from pg_stat_statements
order by mean_exec_time desc
limit 5;

کالم کے نام ورژن کے مطابق بدلتے ہیں: PostgreSQL 13 اور بعد کے ورژن mean_exec_time دکھاتے ہیں، جبکہ پرانے ورژن اسے mean_time کہتے ہیں، اس لیے جانچیں \d pg_stat_statements سے، اگر وہ استفسار غلطی دے۔ یہ اقدار منصوبہ بندی کو خارج کرتی ہیں اور آپ کے کلائنٹ تک سفر کو بھی خارج کرتی ہیں۔ یہی اخراج انہیں موازنے کے لیے مفید بناتا ہے۔

آنے جانے کی گنتی کریں، صرف ملی سیکنڈ نہیں

دو سو چھوٹے منحصر بیانات سے بنی رپورٹ راستے کی شامل کردہ کسی بھی تاخیر کو دو سو سے ضرب دیتی ہے۔ ایک بیان جو دس لاکھ قطاریں واپس کرتا ہے وہ تاخیر ایک بار ادا کرتا ہے اور پھر طویل عرصے بینڈوتھ ادا کرتا ہے۔ دونوں کلائنٹ ٹائمر میں یکساں نظر آتے ہیں، اور دونوں کو متضاد اصلاحات درکار ہیں۔

بیانات کی تعداد کا اندازہ لگانے کے بجائے اسے ناپیں۔ کل پڑھیں، رپورٹ ایک بار چلائیں، پھر دوبارہ پڑھیں اور تفریق کریں۔

select sum(calls) as calls from pg_stat_statements;
-- run the report here
select sum(calls) as calls from pg_stat_statements;

اگر ڈیلٹا بڑا ہو اور سرور پر ہر بیان سستا ہو، تو بیچنگ وہ اصلاح ہے جو فائدہ دیتی ہے۔ منحصر استفسارات کو ملائیں، ایک مجموعہ بنیاد بیان استعمال کریں، یا کرسر سے لوپ چلائیں۔ متعامل psql میں، \set FETCH_COUNT 1000 بڑا نتیجہ بیچوں میں آتا ہے اور منتقلی اور کلائنٹ میموری کا رویہ بدلتا ہے۔ یہ سرور کا کام کم نہیں کرتا، اس لیے سست استفسار کو نہیں بچائے گا۔

سرنگ کو دوبارہ ارسال اور MTU رکاوٹوں کے لیے جانچیں

جب چھوٹے بیانات تیز ہوں اور بڑے نتائج آدھے راستے پر رک جائیں، تو استفسار عام طور پر ٹھیک ہوتا ہے اور راستہ نہیں۔ جس سرنگ کا MTU نیچے کی کڑی سے کم ہو، اس کے ساتھ مسدود ICMP مل کر بالکل وہی نمونہ بناتا ہے: پہلے پیکٹ آتے ہیں، بڑے غائب ہو جاتے ہیں، اور منتقلی دوبارہ کوشش کرنے تک لٹکی رہتی ہے۔ کلائنٹ طرف کے دوبارہ ارسال کے کاؤنٹر یہ دکھاتے ہیں۔

جان بوجھ کر سست منتقلی چلنے کے دوران ساکٹ اور کرنل کاؤنٹر دیکھیں۔ دوبارہ ارسال کی رقمیں جمعی ہوتی ہیں، اس لیے ایک نمونہ پڑھنے کے بجائے پہلے اور بعد میں نوٹ کریں۔

ss -tin dst 10.40.0.12
netstat -s | grep -iE "retransmit|segments retransmitted"
ping -M do -s 1400 -c 3 10.40.0.12

منتقلی کے دوران بڑھنے والے دوبارہ ارسال، 1400 بائٹ پر کامیاب مگر 1472 پر ناکام ping کے ساتھ، ڈیٹابیس کے بجائے MTU مسئلے کی طرف اشارہ کرتے ہیں۔ سرنگ انٹرفیس کا MTU کم کرنا یا گیٹ وے پر MSS دبانا معمول کی اصلاح ہے، اور وہی تین احکام بعد میں اس کی تصدیق کرتے ہیں۔ اگر منتقلی اب بھی سست ہو اور دوبارہ ارسال ہموار رہیں، تو نقصان کے بجائے سرنگ کو دی گئی بینڈوتھ کی طرف دیکھیں۔

ایک مختصر ترتیب اگلی سست رپورٹ کو محیط ہے: ایک بیان کا مقامی، LAN پر اور VPN کے ذریعے موازنہ کریں؛ EXPLAIN یا pg_stat_statements سے سرور کا عمل پڑھیں؛ ایک بار چلانے سے پہلے اور بعد میں کال گنیں؛ اور بڑا نتیجہ حرکت کرتے وقت دوبارہ ارسال دیکھیں۔ ہر قدم راستے کا ایک طرف خارج کرتا ہے۔ ان میں سے کوئی بھی یہ اندازہ لگانے کو نہیں کہتا کہ کون سا جزو دوبارہ شروع کرنا ہے۔

متعلقہ مضامین