کوئری پلان سے شروع کریں، پھر سب سے بڑی لاگت کو ٹھیک کریں۔ / استعمال کریں تاکہ دیکھ سکیں کہ ڈیٹا بیس اصل میں کیا کرتا ہے، صحیح شامل کریں، کوئریز کو ختم کریں، اور صرف وہی ڈیٹا منتخب کریں جس کی آپ کو ضرورت ہے۔
کوئری پلان سے شروع کریں، پھر سب سے بڑی لاگت کو ٹھیک کریں۔ / استعمال کریں تاکہ دیکھ سکیں کہ ڈیٹا بیس اصل میں کیا کرتا ہے، صحیح شامل کریں، کوئریز کو ختم کریں، اور صرف وہی ڈیٹا منتخب کریں جس کی آپ کو ضرورت ہے۔
EXPLAINEXPLAIN ANALYZEEXPLAIN ANALYZE execution plan اور حقیقی timings دکھاتا ہے۔ بڑی ٹیبل پر Seq Scan کلاسیکی انتباہ ہے:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;
-- Seq Scan on orders (cost=0.00..18500 rows=120)
-- Filter: (customer_id = 42)
-- rows removed by filter: 999880 ← scanned the whole table!
ایک index مکمل scan کو تیز lookup میں تبدیل کرتا ہے:
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- Now: Index Scan using idx_orders_customer (cost=0.42..8.5 rows=120)
-- 1,000,000-row scan → ~120-row lookup
Indexes کے لکھنے پر اثر ہوتا ہے: ہر INSERT/UPDATE کو index کو بھی اپڈیٹ کرنا پڑتا ہے، اس لیے ان columns کو index کریں جن پر آپ filter/join/sort کرتے ہیں — ہر column کو نہیں۔ ایک composite index (customer_id, created_at) WHERE customer_id = ? ORDER BY created_at کو ایک structure میں serve کرتا ہے۔
N+1 problem — ایک list کے لیے ایک کوئری، پھر ہر row کے لیے ایک — سستی کی اہم وجہ ہے۔ اسے eager loading، JOIN، یا batched IN (...) سے بدل دیں:
-- N+1: 1 + 100 queries
SELECT * FROM orders; -- then per order: SELECT * FROM users WHERE id = ?
-- Fixed: one JOIN, only needed columns
SELECT o.id, o.total, u.name
FROM orders o JOIN users u ON u.id = o.user_id;
نیز صرف ضروری columns منتخب کریں (SELECT * سے بچیں) اور paginate کریں LIMIT/keyset pagination سے تاکہ آپ کبھی لاکھوں rows load نہ کریں۔
ڈیٹا بیس سب سے عام bottleneck ہے۔ Plan کو پڑھنا آپ کو بتاتا ہے کہ کوئری کیوں سست ہے اندازے کی بجائے؛ صحیح index، N+1 کو ہٹانا، اور نتیجے کو کاٹنا معمول کے طور پر second-long کوئریز کو millisecond والی کوئریز میں تبدیل کرتے ہیں — بغیر hardware کو scale کیے۔