কোয়েরি প্ল্যান দিয়ে শুরু করুন, তারপর সবচেয়ে বড় খরচ ঠিক করুন। EXPLAIN/ ব্যবহার করে দেখুন ডেটাবেস আসলে কী করে, সঠিক যোগ করুন, কোয়েরি দূর করুন এবং শুধুমাত্র প্রয়োজনীয় ডেটা নির্বাচন করুন।
কোয়েরি প্ল্যান দিয়ে শুরু করুন, তারপর সবচেয়ে বড় খরচ ঠিক করুন। EXPLAIN/ ব্যবহার করে দেখুন ডেটাবেস আসলে কী করে, সঠিক যোগ করুন, কোয়েরি দূর করুন এবং শুধুমাত্র প্রয়োজনীয় ডেটা নির্বাচন করুন।
EXPLAIN ANALYZEEXPLAIN ANALYZE এক্সিকিউশন প্ল্যান এবং বাস্তব সময় দেখায়। একটি বড় টেবিলের উপর একটি 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!
একটি ইনডেক্স একটি সম্পূর্ণ স্ক্যানকে দ্রুত লুকআপে পরিণত করে:
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
ইনডেক্সের লেখার ক্ষেত্রে খরচ রয়েছে: প্রতিটি INSERT/UPDATE অবশ্যই ইনডেক্সও আপডেট করবে, তাই যে কলামগুলিতে আপনি ফিল্টার/জয়েন/সর্ট করেন সেগুলিতে ইনডেক্স করুন — প্রতিটি কলামে নয়। একটি composite ইনডেক্স (customer_id, created_at) WHERE customer_id = ? ORDER BY created_at এক কাঠামোতে পরিবেশন করে।
N+1 সমস্যা — একটি তালিকার জন্য একটি কোয়েরি, তারপর প্রতিটি সারির জন্য একটি — ধীরতার শীর্ষ কারণ। এটিকে 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;
আরও শুধুমাত্র প্রয়োজনীয় কলাম নির্বাচন করুন (SELECT * এড়ান) এবং paginate করুন LIMIT/keyset pagination দিয়ে যাতে আপনি কখনও লক্ষ লক্ষ সারি লোড না করেন।
ডেটাবেস সবচেয়ে সাধারণ বটলনেক। প্ল্যান পড়া আপনাকে বলে কেন একটি কোয়েরি ধীর অনুমান করার পরিবর্তে; সঠিক ইনডেক্স, N+1 অপসারণ এবং ফলাফল সেট ট্রিম করা নিয়মিতভাবে সেকেন্ড-দীর্ঘ কোয়েরিগুলিকে মিলিসেকেন্ড-এ পরিণত করে — হার্ডওয়্যার স্কেল না করে।