Query Optimization

কুয়েরি অপটিমাইজেশন কী?

কুয়েরি অপটিমাইজেশন হলো এমন একটি প্রসেস, যেখানে DBMS ঠিক করে একটি Query কীভাবে সবচেয়ে দ্রুত ও কার্যকরভাবে চালানো যায়। একই ফলাফল পাওয়ার একাধিক উপায় থাকতে পারে, কিন্তু সবগুলোর গতি এক নয়।

লাইব্রেরির উদাহরণে, এলোমেলোভাবে শেলফ ঘেঁটে বই খোঁজা ধীর, আর সূচিপত্র (Index) ধরে খোঁজা দ্রুত। অপটিমাইজেশন হলো সেই বুদ্ধিমান পথটি বেছে নেওয়ার কাজ।

কেন গুরুত্বপূর্ণ?

  • দ্রুত ফলাফল: Query হালকা হলে Database-এর লোড কমে।

  • Server Load কমে: কম CPU ও RAM ব্যবহার হয়।

  • ভালো User Experience: ওয়েবসাইট বা অ্যাপ দ্রুত লোড হয়।

  • Scalability: ডাটা বাড়লেও Performance ভালো থাকে।

Query Optimizer কীভাবে কাজ করে?

Query লেখার পর DBMS-এর Query Optimizer একাধিক Execution Plan তৈরি করে, প্রতিটির আনুমানিক খরচ (Cost) হিসাব করে এবং সবচেয়ে সস্তাটি বেছে নেয়। এই হিসাবে সে Table-এর Statistics (রো সংখ্যা, ডাটার বণ্টন) ব্যবহার করে। তাই Statistics পুরোনো হলে Optimizer ভুল Plan বেছে নিতে পারে।

অপটিমাইজ করার কৌশল

১. Index ব্যবহার করুন

Primary Key, Foreign Key এবং যেসব কলাম WHERE, JOIN, ORDER BY-এ বেশি ব্যবহৃত হয়, সেগুলোতে Index দিন। Index থাকলে Database পুরো টেবিল না ঘেঁটে সরাসরি ডাটা খুঁজে পায়।

২. অপ্রয়োজনীয় ডাটা বাদ দিন

  • সব রো না এনে WHERE দিয়ে শুধু দরকারি রো আনুন।

  • SELECT * এড়িয়ে শুধু প্রয়োজনীয় কলাম আনুন। এতে ডাটা Transfer কমে এবং Covering Index ব্যবহারের সুযোগ তৈরি হয়।

৩. JOIN অপটিমাইজ করুন

  • Index আছে এমন কলামের ওপর JOIN করুন।

  • আগে WHERE দিয়ে রো সংখ্যা কমিয়ে নিন।

  • LEFT JOIN শুধু তখনই ব্যবহার করুন, যখন মিল না থাকা রোও দরকার।

সংশোধনী: মূল লেখায় বলা হয়েছিল INNER JOIN "বেশি কার্যকর"। বাস্তবে INNER ও LEFT JOIN-এর অর্থ ভিন্ন, তাই প্রয়োজন অনুযায়ী বেছে নিতে হয়। গতির পার্থক্য মূলত Index ও ডাটার ওপর নির্ভর করে।

৪. LIMIT ও Pagination

LIMIT ও OFFSET দিয়ে নির্দিষ্ট সংখ্যক ডাটা আনা যায়। তবে OFFSET বড় হলে Database-কে সেই সব রো পড়ে বাদ দিতে হয়, ফলে ধীর হয়ে যায়। বড় ডাটায় Keyset Pagination ভালো, যেখানে শেষ দেখা ID-র পর থেকে পরের অংশ আনা হয়।

৫. Execution Plan বিশ্লেষণ করুন

EXPLAIN ANALYZE দেখায় Query আসলে কীভাবে চলেছে এবং কোথায় সময় যাচ্ছে।

  • Seq Scan: পুরো টেবিল স্ক্যান, Index ব্যবহার হচ্ছে না

  • Index Scan / Index Only Scan: Index ব্যবহার হচ্ছে

  • Estimated ও Actual রো সংখ্যায় বড় ফারাক থাকলে Statistics পুরোনো হতে পারে

সতর্কতা: EXPLAIN ANALYZE Query সত্যিই চালায়। তাই UPDATE বা DELETE-এ ব্যবহার করলে ডাটা বদলে যাবে।

৬. Index নষ্ট করে এমন লেখা এড়িয়ে চলুন

  • কলামে Function প্রয়োগ করা (যেমন নামকে ছোট হাতের অক্ষরে বদলে তুলনা, বা তারিখ থেকে বছর বের করে তুলনা)

  • শুরুতে Wildcard দিয়ে LIKE ব্যবহার করা

এর বদলে কলামটি যেমন আছে তেমন রেখে তুলনা করুন, আর তারিখের ক্ষেত্রে Range Condition ব্যবহার করুন।

৭. N+1 Query সমস্যা এড়ান

Application-এ লুপের ভেতরে বারবার Query চালানো একটি সাধারণ ভুল। ১০০টি অর্ডারের জন্য ১০০টি আলাদা Query না চালিয়ে একটি JOIN বা Batch Query দিয়ে একসাথে আনুন। Django-তে select_related ও prefetch_related এই কাজ করে।

৮. অন্যান্য কৌশল

  • Caching: বারবার একই Query হলে ফলাফল Redis-এ রাখুন

  • Statistics হালনাগাদ: নিয়মিত ANALYZE চালান

  • Slow Query Log: ধীর Query শনাক্ত করে আগে সেগুলোই ঠিক করুন

  • Partitioning: অত্যন্ত বড় টেবিলকে ভাগ করুন

সমস্যা ও সমাধান

সমস্যা

সমাধান

SELECT *

শুধু প্রয়োজনীয় কলাম

Filter কলামে Index নেই

Index তৈরি

কলামে Function প্রয়োগ

Range Condition-এ বদলানো

বড় OFFSET

Keyset Pagination

লুপে Query (N+1)

JOIN বা Batch Query

পুরোনো Statistics

ANALYZE

কুয়েরি অপটিমাইজেশন শুধু দ্রুত ফলাফলের বিষয় নয়, এটি Server Load কমায়, Scalability নিশ্চিত করে এবং User Experience ভালো রাখে। সবচেয়ে কার্যকর পদ্ধতি হলো আন্দাজে না করে আগে EXPLAIN ANALYZE দিয়ে মেপে দেখা, তারপর ধীর অংশটি ঠিক করা।