০০ যে প্রশ্নগুলোর উত্তর খুঁজবো
আগের সব সেশন ছিলো database এর আশেপাশের জিনিসপত্র নিয়ে। এই সেশনে আমরা database এর ভেতরে একটু ঢুঁ মারবো। প্রতিটা প্রশ্নের উত্তর জানা হয়ে গেলে আপনি বুঝবেন একটা query কীভাবে full scan থেকে binary search এ পরিণত হয়।
- ১ Database এর কাছে একটা row চাইলে, database কীভাবে সেই row টা খুঁজে পায়?
- ২ বড় table এ একটা row খুঁজে বের করা তো slow। lookup fast করবো কীভাবে?
- ৩ Index আসলে কী? (কোন data structure ইউজ হয়?)
- ৪ Index যদি read fast করে, তাহলে প্রতিটা column index করি না কেন?
- ৫ একাধিক column এ filter query করবার জন্য কীভাবে index করবো?
- ৬ কখন index কাজে আসে না, বরং উল্টো ক্ষতি করে?
- ৭ Full picture: index আগের সব কিছুর সাথে কীভাবে কানেক্টেড?
০১ Database এর কাছে একটা row চাইলে, database কীভাবে সেই row টা খুঁজে পায়?
ধরুন আপনার একটা users table আছে, আর সেই table এ ১ কোটি row জমা আছে। এবার আপনি query লিখলেনঃ
SELECT * FROM users WHERE email = 'roy@example.com';
Table টা একটা বিশাল খাতার মতো। Row গুলো insertion order এ store করা থাকে (user 1, user 2, user 3…), email অনুযায়ী সাজানো থাকে না। তাই roy@example.com email টা খুঁজতে database একে একে প্রতিটা row চেক করেঃ
Row 1: alice@example.com - নো ম্যাচ। Row 2: bob@@example.com? - নো ম্যাচ।। ... Row 7,234,891: roy@@example.com? - ম্যাচ।
অর্থাৎ match না পাওয়া পর্যন্ত database একটার পর একটা row পড়তেই থাকে। এটাকে বলে full table scan; m সংখ্যক row এর জন্য এর complexity O(m)।
শুধু একটা সাধারণ lookup এর জন্যই database প্রতি সেকেন্ডে কোটি কোটি comparison করে। এতে system overloaded হয়ে যায়।
কোনো সাহায্য ছাড়া একটা row খোঁজা মানে শুরু থেকে এক এক করে scan করা। ছোট table এ এতে কোনো অসুবিধা নেই, কিন্তু মিলিয়ন বা বিলিয়ন row হলে database ভয়ংকর রকম slow হয়ে যায়। আর এটা ঘটে প্রতিটা query তে।
০২ বড় table এ একটা row খুঁজে বের করা তো slow। lookup fast করবো কীভাবে?
Phone book এর analogy টা দেখি। একটা কাগজের phone book এ লাখ লাখ নাম থাকে। একটা নাম খুঁজতে গেলে আপনি নিশ্চয়ই page 1 থেকে পড়া শুরু করবেন না। আপনি বইটা মাঝখানে খুলবেন, একটা নাম দেখবেন, তারপর ঠিক করবেন আপনার খোঁজা নামটা এটার আগে নাকি পরে। প্রতি ধাপে বাকি page এর অর্ধেক বাদ পড়ে যায়। এটাকেই বলে binary search।
জাদুকরী যে property টা binary search কে সম্ভব করেছে সেটা হলোঃ phone book টা sorted। Binary search শুধু sorted data তেই কাজ করে। নাম গুলো random order এ থাকলে একটা নাম দেখে পরের নামটা কোথায় আছে সেটা বোঝার কোনো উপায় থাকতো না।
Binary search এ Speed এর পার্থক্যটা কিন্তু বিশাল
১ কোটি row এর মধ্য থেকে একটা নাম খুঁজতেঃ
- Full scan (unsorted): সর্বোচ্চ ১,০০,০০,০০০ টা read।
- Binary search (sorted): প্রায় ২৪টা read (কারণ ২২৪ ≈ ১.৬ কোটি; ১ কোটিকে প্রায় ২৪ বার অর্ধেক ভাগে ভাগ করা যায়)।
Data দ্বিগুণ হলে binary search এ মাত্র একটা step বাড়ে, কিন্তু full scan এর কাজ দ্বিগুণ হয়ে যায়। scaling এর সময় এই ছোট্ট পার্থক্যটাই ঠিক করে দেয় কোন system টিকে থাকবে আর কোনটা ভেঙে পড়বে।
Sorting fast search কে unlock করে। Data sorted রাখুন, binary-search ব্যবহার করুন, search complexity O(m) থেকে O(log m) এ নামিয়ে ফেলুন।
একটা catch আছে
একটা table কে physically একসাথে শুধু একভাবেই sort করা যায়। Email দিয়ে sort করলে email order টা থাকে; কিন্তু তারপর username দিয়ে sort করলে email order টা নষ্ট হয়ে যায়। শুধু শেষ sort টাই অ্যাপ্লাই থাকে। অথচ আমরা প্রায়ই অনেক column এ search করি (email, username, phone)। সব column অনুযায়ী একটা table কে একসাথে sorted রাখা যায় না।
০৩ Index আসলে কী? (কোন data structure ইউজ হয়?)
বুদ্ধিমানের কাজ হলো পুরো table কে sort না করা। বরং একটা ছোট, আলাদা, sorted structure বানানো, যেটাতে শুধু search column টা থাকে আর সেই সাথে full row এর জন্য একটা pointer থাকে।
TABLE (insertion order, unsorted): Row 1: id:1, email: roy@example.com Row 2: id:2, email: alice@example.com Row 3: id:3, email: bob@example.com INDEX on email (sorted, আলাদা structure): alice@example.com → Row 2 bob@example.com → Row 3 roy@example.com → Row 1
Search WHERE email = 'roy@example.com':
- Sorted index এ binary-search করুন; প্রায় ২৪ step এ
roy@example.comপাওয়া যায়। - Entry টা Row 1 এর দিকে point করে।
- সরাসরি table এর Row 1 এ চলে যান।
Table কে physically sort না করেই আপনি binary-search speed পেয়ে গেলেন। আর index যেহেতু আলাদা, তাই অনেকগুলো index বানানো যায়, প্রতিটা search প্রয়োজনের জন্য একটা করেঃ
INDEX on email → row এর দিকে pointer INDEX on username → row এর দিকে pointer INDEX on phone → row এর দিকে pointer
Index হলো এক (বা একাধিক) column এর একটা আলাদা, sorted copy, যেটাতে full row এর দিকে pointer থাকে। Table কে sort না করেই এটা একটা column binary-search করতে দেয়, আর আপনি চাইলে অনেকগুলো index রাখতে পারেন।
এটা আসলে একটা B-tree
আসল database গুলো index কে একটা flat sorted list হিসেবে রাখে না, রাখে একটা B-tree (B+ tree) হিসেবে (একটা বিশাল flat list এর মাঝখানে কিছু insert করতে গেলে পুরোটা shift করতে হতো)। Intuition টা হলো: এটা একটা sorted tree, যেটার উপর থেকে নিচের দিকে হেঁটে নামলে প্রতি step এ range টা সরু হয়ে আসে।
Key property গুলো:
- Data sorted রাখে (binary-search-style lookup)।
- Insert আর delete efficiently handle করে (সব কিছু re-shift করতে হয় না)।
- Lookup O(log m), মানে “১ কোটি row তে ~২৪ step” এর সেই speed।
কেউ যখন বলে “database টা index ব্যবহার করে”, তখন প্রায় সবসময় সে একটা B-tree index এর কথাই বোঝায়। Mental model: একটা sorted tree, যেটা ধরে নিচে নেমে দ্রুত জিনিস খুঁজে পান।
০৪ প্রতিটা operation এ table আর index এ কী হয়
এটাই পুরো mechanical picture। Setup: একটা users table, যার email এর উপর একটা index আছে।
TABLE (insertion order): INDEX on email (sorted): Row 1: id:1, email: roy@example.com alice@example.com → Row 2 Row 2: id:2, email: alice@example.com bob@example.com → Row 3 Row 3: id:3, email: bob@example.com roy@example.com → Row 1
READ (SELECT): সুবিধাটা
Query: SELECT * FROM users WHERE email = 'roy@example.com'
Index ছাড়া (full scan): worst case এ সব m টা row scan করতে হয়। Cost O(m), slow।
Index সহ (B-tree binary search): index এ roy@example.com binary-search করুন (~২৪ step), তারপর pointer ধরে সরাসরি Row 1 এ চলে যান। Cost O(log m), fast। এটাই পুরো সুবিধা।
(Non-indexed column এ read করলে কোনো সুবিধা নেই; সেটা আবার full scan এ ফিরে যায়। Index শুধু যে column টা cover করে, সেই column এর read এ help করে।)
INSERT a new row
id:4, email: carol@example.com insert করুন।
Step 1 - table এ row লেখা (শেষে, insertion order): Row 4: carol@example.com ← নতুন row Step 2 - index এ সঠিক SORTED position এ insert: alice@example.com → Row 2 bob@example.com → Row 3 carol@example.com → Row 4 ← sorted জায়গায় বসলো, শেষে না roy@example.com → Row 1
Cost: ১ টা table write আর প্রতি index এ ১ টা B-tree insert (জায়গা খুঁজতে ~log m)।
UPDATE an indexed column
Row 3 এর email bob@example.com থেকে zoe@example.com এ বদলান। Index এ value এর sorted position টা বদলে যায়, তাই এটা আসলে হয়ে দাঁড়ায় পুরোনো entry delete আর নতুন entry insert:
Step 1 - table এ value বদলান: Row 3: zoe@example.com Step 2 - index থেকে পুরোনো entry delete (bob@example.com চলে গেলো) Step 3 - নতুন sorted position এ insert: alice@example.com → Row 2 carol@example.com → Row 4 roy@example.com → Row 1 zoe@example.com → Row 3 ← নতুন sorted position
Indexed column update করা মানে delete + insert। এটাই সবচেয়ে expensive operation।
UPDATE a non-indexed column
Row 1 এর last_login_time বদলান। last_login_time indexed না, তাই email index এ কোনো হাত পড়ে না। Cost: শুধু table write। Index এ কোনো কাজ নেই।
DELETE a row
Row 2 (alice@example.com) delete করুন। Table থেকে row টা সরান, আর index থেকে তার entry টাও সরান। Cost: ১ টা table delete আর প্রতি index এ ১ টা B-tree delete।
পুরো operations table
| Operation | Table | Index (প্রতি index) | Cost |
|---|---|---|---|
| READ on indexed column | pointer ধরে row এ jump | B-tree binary search | O(log m), fast (সুবিধাটা) |
| READ on non-indexed column | full table scan | index unused | O(m), slow |
| INSERT | row যোগ | sorted position এ ১ টা insert | table write + n × O(log m) |
| UPDATE indexed column | value বদল | ১ delete + ১ insert (position সরে) | সবচেয়ে expensive |
| UPDATE non-indexed column | value বদল | কিছু না | cheap |
| DELETE | row সরানো | ১ delete | table delete + n × O(log m) |
প্রতিটা write যেসব index এর কোনো changed column cover করে, সেগুলোর সবটায় গিয়ে ছড়ায়। INSERT সব index এ ছড়ায়। DELETE সব index এ ছড়ায়। UPDATE শুধু changed column এর index এ ছড়ায়, আর সেখানে double cost (delete + insert), কারণ sorted position টা সরে যায়।
০৫ Index যদি read fast করে, তাহলে প্রতিটা column index করি না কেন?
কারণ index free না। n টা index সহ একটা row insert করার cost মোটামুটিঃ
১ (table write) + n × log(m)
এখানে n হলো index সংখ্যা, আর m হলো table এর row সংখ্যা। প্রতিটা relevant write এ প্রতিটা index কে sorted রাখতে হয়।
| আরো index | প্রভাব |
|---|---|
| Read (indexed column এ) | Faster (full scan এর বদলে binary search) |
| Write (insert/update/delete) | Slower (প্রতিটা index maintain করতে হয়) |
| Storage | More (প্রতিটা index একটা আলাদা structure) |
যে column এ search করেন সেগুলোই index করুন, প্রতিটা column না। প্রতিটা index আসলে একটা বাজি: “এটা যে read fast করছে, সেটা যে write slow করছে তার চেয়ে বেশি মূল্যবান”। Access pattern অনুযায়ী index করুন।
Guideline গুলো:
- প্রায়ই search হয় এমন column: index করুন।
- খুব কম search হয় কিন্তু প্রায়ই write হয় এমন column: index করবেন না।
- Write-heavy table: যত কম index তত ভালো।
- Read-heavy table: বেশি index লাভজনক।
- প্রায়ই বদলায় এমন column index করলে সবচেয়ে বেশি ক্ষতি (প্রতিটা change মানে B-tree তে delete + insert)।
উদাহরণ: Logs Table
একটা logs table এ সেকেন্ডে ৫০,০০০ insert হয়, কিন্তু search হয় সপ্তাহে একবার।
- Write-heavy, read-rare: যত কম index তত ভালো (প্রতিটা index সেকেন্ডে ৫০,০০০ write এর উপর tax বসায়, শুধু সপ্তাহে একবার এর সুবিধার জন্য)।
- শুধু সেই column টাই index করুন যেটা weekly debugging search এ আসলে filter হয়, প্রায় সবসময় সেটা হলো logtime (debugging সাধারণত time-range ধরে হয়: “২টা থেকে ৩টার মধ্যের log”)।
- দ্বিতীয় একটা index (যেমন created_by) যোগ করবেন না, যতক্ষণ না সত্যিই সেটা দিয়ে query করছেন।
- Bonus: log একবারই লেখা হয়, তাই indexed column কখনো update হয় না; expensive update cost পুরোপুরি এড়িয়ে যায়।
বাস্তবে সবচেয়ে common ভুল হলো actual query না দেখে অনুমান করে index column বেছে নেওয়া। যে query গুলো আপনি আসলে চালান, সেগুলোর জন্যই index করুন।
০৬ একাধিক column এ filter query করবার জন্য কীভাবে index করবো?
একটা composite index (compound বা multi-column) হলো দুই বা তার বেশি column একসাথে নিয়ে বানানো একটা index:
INDEX on (last_name, first_name)
এটা প্রথম column দিয়ে sort করে, tie হলে দ্বিতীয় দিয়ে, তারপর তৃতীয় দিয়ে; ঠিক একটা phone book এর মতো যেটা (last_name, first_name) দিয়ে sorted:
Rahman, Abdul Rahman, Fatima Rahman, Karim ← আগে last name দিয়ে group... Rahman, Zara ...তারপর প্রতিটা last name এর ভেতরে first name দিয়ে sort Roy, Amit
Left-prefix rule (যেখানে সবাই আটকায়)
একটা (A, B, C) composite index ওই query গুলোতেই help করে, যেগুলো একটা continuous left prefix এ filter করে: A, বা A+B, বা A+B+C। যেসব query প্রথম column টা skip করে, সেগুলোতে এটা help করে না।
(last_name, first_name) index দিয়ে:
WHERE last_name = 'Rahman': help করে (left prefix; Rahman রা একসাথে group থাকে)।WHERE last_name = 'Rahman' AND first_name = 'Karim': help করে (full prefix)।WHERE first_name = 'Karim': help করে না (প্রথম column skip; Karim রা সব last name এর মধ্যে ছড়িয়ে আছে)।
Index টা আগে প্রথম column দিয়ে sorted। দ্বিতীয় column টা শুধু প্রথম column এর group গুলোর ভেতরে sorted। প্রথমটা skip করলে দ্বিতীয় column এর order এর আর কোনো অর্থ থাকে না।
দুইটা failure mode: গুরুত্বপূর্ণ পার্থক্য
- একটা MIDDLE column skip: partial help। Gap এর আগের prefix টা কাজ করে; index ততদূর পর্যন্ত সরু করে, তারপর degrade করে।
- FIRST column skip: কোনো help নেই। Index এ ঢোকার entry point ই নেই।
(country, city, age) দিয়ে উদাহরণ:
WHERE country='BD' AND age=25(middlecityskip): partial; index BD row এ jump করে (প্রথম column কাজ করে), তারপর সেগুলোর মধ্যে age=25 scan করে (city missing বলে chain ভেঙে গেছে)।WHERE city='Dhaka'(প্রথমcountryskip): no help; entry point নেই।WHERE city='Dhaka' AND age=25(প্রথমcountryskip): no help; indexed column এ filter করছেন ঠিকই, কিন্তু প্রথম column missing, তাই index অকেজো।
প্রথম column ছাড়া index টা একদমই ব্যবহার করা যায় না, query তে পরের যত column ই থাকুক না কেন। এই কারণেই
(department, role, salary) index এর বিপরীতে (role, salary) দিয়ে filter করলে কোনো help পাওয়া যায় না; department টা missing।
Composite index design
Column গুলো access pattern অনুযায়ী order করুন: যে column আপনি সবসময় filter করেন সেটা আগে, আর যেটা মাঝে মাঝে অতিরিক্ত filter করেন সেটা পরে।
উদাহরণ: ধরুন query গুলো হলো “customer X এর সব order” আর “customer X এর order একটা date range এ”। তাহলে index হবে (customer_id, order_date)। customer_id দুই query তেই ব্যবহৃত left prefix। (এটা “সব customer এর একটা date এর সব order” এ help করতো না; সেটা শুধু date এ filter করে, যেটা left prefix না।)
Covering index (যে term টা জানা দরকার)
একটা index এ যদি query এর দরকারি সব column থাকে, তাহলে database table এ না গিয়েই পুরো উত্তর index থেকেই দিয়ে দিতে পারে। (last_name, first_name) index এর বিপরীতে SELECT first_name WHERE last_name='Rahman' query তে দুইটা column ই index এ আছে, তাই table এ jump করার দরকার পড়ে না। এটাকে বলে covering index (“query এর সব column cover করে”)। Row lookup skip করে বলে এটা faster।
০৭ কখন index কাজে আসে না, বরং উল্টো ক্ষতি করে?
Index help করে না যখন:
- Query একটা non-indexed column এ filter করে (full scan)।
- Query একটা composite index এর প্রথম column skip করে (entry point নেই)।
- Table খুব ছোট (full scan এমনিতেই fast; index এর overhead এর দাম নেই)।
Index ক্ষতি করে যখন:
- Table write-heavy আর index টা read এ খুব কম ব্যবহৃত হয় (শুধু write tax আর storage cost)।
- প্রায়ই বদলায় এমন একটা column index করেন (প্রতিটা change মানে B-tree তে delete + insert)।
- Over-index করেন (“প্রতিটা column index করা”); বেশিরভাগ index কখনো ব্যবহারই হয় না, অথচ সবগুলো প্রতিটা write slow করে আর storage খায়।
আগে actual query দেখুন, তারপর সেগুলোর সাথে match করে index করুন। যে index এর বিপরীতে আপনি query করেন না, সেটা শুধুই cost, কোনো benefit নেই।
০৮ Full picture: index আগের সব কিছুর সাথে কীভাবে কানেক্টেড?
সেশন ১ থেকে ৬ এর সব কিছু ছিলো database এর চারপাশে। Index থাকে একটা single database এর ভেতরে, আর প্রতিটা query কে fast করে।
Connection গুলো
- Performance pillar: DB এর ভেতরে index ই সবচেয়ে বড় read-performance lever (O(m) থেকে O(log m))।
- Caching (S4): দুটোই read speed এর জন্য write cost আর storage এর সাথে trade করে। Cache DB কে এড়ায়; আর index DB কে fast করে যখন DB এড়ানো যায় না।
- Sharding (S5): shard key ঠিক করে কোন machine; আর index ঠিক করে ওই machine এ কোথায়। দুটোই access pattern দিয়ে চালিত।
- Recurring theme: replication, caching, sharding এর মতোই, index ও free না। Access pattern এর জন্য optimize করুন, আর সেটা যে cost কেনে তা accept করে নিন।
- Actual query দেখুন; যে column এ filter / search / join করেন সেগুলো index করুন।
- Read-heavy table: বেশি index লাভজনক।
- Write-heavy table: যত কম index তত ভালো।
- Multi-column filter: composite index, left-prefix rule অনুযায়ী order করা।
- প্রায়ই বদলায় এমন column: দুইবার ভাবুন (indexed-column update double cost)।
০৯ মগজে প্রেশার দিন
আগে নিজে ভাবুন। তারপর দেখুন: সবাই যেভাবে ভাবে, কেন সেটা অসম্পূর্ণ, আর আসল insight টা কোথায়।
উত্তর দেখুন আগে নিজে ভাবুন
সবাই যেভাবে ভাবে
“Index search কে O(log n) করে। Write slow হয় কারণ নতুন row টাকে সঠিক জায়গায় বসাতে হয়। অনেক index থাকলে cost index সংখ্যার সাথে বাড়ে।”
Direction টা ঠিক আছে, কিন্তু একটা জায়গা সবাই miss করে।
যে জায়গাটা tighten করা দরকার
শুধু insert না; insert, delete, আর indexed-column update সবগুলোই index maintain করে। Read হলো sorted structure এ একটা O(log n) binary search। Write slow হয় কারণ প্রতিটা নতুন row কে প্রতিটা index এর sorted position এ বসাতে হয়, আর সেই cost index সংখ্যার সাথে বাড়তে থাকে।
Indexed column update সবচেয়ে expensive: এটা delete + insert, কারণ value এর sorted position টা সরে যায়। তাই প্রায়ই বদলায় এমন column index করা সবচেয়ে বেশি ক্ষতিকর।
উত্তর দেখুন আগে নিজে ভাবুন
সঠিক choice আর কেন
Composite index (customer_id, order_date)। customer_id দুই query তেই ব্যবহৃত left prefix; আর order_date query (খ) এর জন্য সেটাকে extend করে।
উল্টে দিলে কী হতো
(order_date, customer_id) করলে query (ক) ভেঙে যেতো; “customer X এর সব order” তে কোনো date নেই, তাই প্রথম column
missing, index অকেজো। তাই access pattern অনুযায়ী order করাই সঠিক।
যে column সবসময় filter করেন সেটা আগে রাখুন। Left-prefix rule ঠিক করে index কোন query accelerate করবে।
উত্তর দেখুন আগে নিজে ভাবুন
সবাই যেভাবে ভাবে
“Index এর insert, update, delete cost আছে। n টা column index করলে cost n গুণ বাড়ে। শুধু যে column এ read frequent সেগুলোই index করুন।”
Key point গুলো ঠিক, কিন্তু আরো দুইটা argument যোগ করা যায়।
আরো ধারালো পুশব্যাক
প্রতিটা column index করা storage নষ্ট করে (প্রতিটা index আলাদা structure), আর বেশিরভাগ index কখনো ব্যবহারই হবে না। একটা index শুধু সেই query তেই help করে যেটা ওই column এ filter করে। তাই unsearched column index করা মানে শুধু write tax আর storage, zero benefit।
আগে actual query দেখুন, তারপর সেগুলোর সাথে match করে index করুন। Read-heavy হলে index, আর write-heavy হলে কম index আর শুধু priority column। Fit হলে composite index ভাবুন।
১০ যে টার্মগুলো শিখলাম
| টার্ম | মানে |
|---|---|
| Full table scan | একটা match খুঁজতে এক এক করে প্রতিটা row পড়া। O(m)। |
| Binary search | একটা sorted range প্রতি step এ অর্ধেক করে value খোঁজা। O(log m)। শুধু sorted data তে কাজ করে। |
| Index | একটা column এর আলাদা sorted structure, যাতে full row এর দিকে pointer থাকে। |
| B-tree (B+ tree) | Database যে sorted tree structure index এর জন্য ব্যবহার করে; fast lookup আর efficient insert/delete। |
| Composite index | একাধিক column একসাথে নিয়ে index, আগে প্রথম column দিয়ে sorted, তারপর দ্বিতীয়, …। |
| Left-prefix rule | Composite index শুধু তার column গুলোর একটা continuous left prefix এ help করে (A, A+B, A+B+C)। |
| Partial help | একটা middle column skip করা; gap এর আগের prefix টা তখনো কাজ করে। |
| No help (প্রথম column missing) | প্রথম column skip করা; entry point নেই, index অকেজো। |
| Covering index | যে index এ query এর দরকারি সব column থাকে, তাই table lookup লাগে না। |
| Cardinality | একটা column এ distinct value এর সংখ্যা (high cardinality হলে ভালো index candidate)। |
১১ সর্ট সামারী
- Index হলো একটা আলাদা sorted structure (B-tree), যেটা একটা column এর read কে full scan O(m) থেকে binary search O(log m) এ নিয়ে আসে; database এর ভেতরে এটাই সবচেয়ে বড় read-performance lever।
- Index free না: প্রতিটা insert, delete, আর indexed-column update প্রতিটা relevant index কে sorted রাখে, তাই প্রতিটা column না, শুধু যে column এ আসলে query করেন সেগুলোই index করুন।
- Multi-column filter এর জন্য left-prefix rule অনুযায়ী order করা composite index ব্যবহার করুন; এটা একটা continuous left prefix এ help করে (A, A+B, A+B+C), middle column skip করলে partial, আর প্রথম column skip করলে একদমই না।
১২ মনে রাখুন
- Sorting fast search কে unlock করে। Index একটা column কে sorted রাখে, যাতে scan এর বদলে binary-search করা যায়।
- Index শুধু যে column cover করে সেগুলোর read এ help করে। অন্য column এর query কোনো সুবিধা পায় না।
- Index প্রতিটা write এ tax বসায়। বেশি index মানে slower insert/delete/update আর বেশি storage। Reflex এ না, access pattern অনুযায়ী index করুন।
- Composite index এ column এর order একটা design decision. যে column প্রায় সবসময় filter হয় সেটা আগে; left-prefix rule ঠিক করে কোন query accelerate হবে।
- Composite index এর প্রথম column হলো gatekeeper. সেটা skip করলে index অকেজো, query তে বাকি indexed column থাকলেও।
- Indexed-column update double cost (delete + insert). প্রায়ই বদলায় এমন column index করা এড়িয়ে চলুন।
- Caching আর sharding এর মতোই access-pattern চিন্তা। Index হলো universal trade-off এর inside-the-database রূপ: read speed কেনার জন্য write cost দিন।