ডেটাবেস ডিজাইন এবং নরমালাইজেশন
একটি বিল্ডিং তৈরির আগে যেমন ব্লু-প্রিন্ট বা নকশা করতে হয়, তেমনি সফটওয়্যার তৈরির আগে ডেটাবেস ডিজাইন করতে হয়। এই ডিজাইন যদি ভুল হয়, তবে ভবিষ্যতে ডেটা ডুপ্লিকেট হবে, কুয়েরি স্লো হবে এবং ডেটা আপডেট করতে গেলে Anomaly তৈরি হবে।
এই অধ্যায়ে আমরা শিখব কীভাবে একটি Efficient, Scalable এবং Clean ডেটাবেস ডিজাইন করতে হয়।
৭.১ ডেটাবেস ডিজাইন কীভাবে শুরু করবেন? (Senior Approach)
একজন জুনিয়র ডেভেলপার সরাসরি কোড লেখা শুরু করে। কিন্তু একজন সিনিয়র ডেভেলপার বা আর্কিটেক্ট নিচের ধাপগুলো অনুসরণ করেন:
১. Requirement Analysis
সিস্টেমটি আসলে কী ডেটা স্টোর করবে? (যেমন: ই-কমার্স সিস্টেমে ইউজার, প্রোডাক্ট, অর্ডার লাগবে)।
২. Identify Entities
প্রধান অবজেক্টগুলো খুঁজে বের করা (Table) — Users, Products, Orders, Categories.
৩. Identify Attributes
প্রতিটি টেবিলের কলাম কী হবে? User -> id, name, email. Order -> id, total, date.
৪. Define Relationships
কার সাথে কার সম্পর্ক? একজন ইউজার অনেকগুলো অর্ডার দিতে পারে (1-to-Many)। একটি প্রোডাক্ট অনেক ক্যাটাগরিতে থাকতে পারে (Many-to-Many)।
৫. Normalization
ডেটা ডুপ্লিকেশন কমানো এবং স্ট্রাকচার ঠিক করা (নিচে বিস্তারিত আলোচনা করা হলো)।
৬. ER Diagram
ভিজুয়াল ডায়াগ্রাম আঁকা।
৭.২ নরমালাইজেশন (Normalization) কেন প্রয়োজন?
নরমালাইজেশন হলো ডেটাবেসকে ধাপে ধাপে পরিপাটি করার বিজ্ঞান। এর প্রধান উদ্দেশ্য:
- Redundancy কমানো: একই ডেটা বারবার সেভ না করা।
- Consistency: এক জায়গায় ডেটা আপডেট করলে যেন সব জায়গায় আপডেট হয়।
- Storage Optimization: জায়গার অপচয় রোধ করা।
⚠️ Anomalies (সমস্যা) যা নরমালাইজেশন সমাধান করে:
- Insertion Anomaly: ক্যাটাগরি ছাড়া প্রোডাক্ট এড করা যাচ্ছে না।
- Deletion Anomaly: প্রোডাক্ট ডিলিট করলে ক্যাটাগরির তথ্যও হারিয়ে যাচ্ছে।
- Update Anomaly: এক জায়গায় নাম পরিবর্তন করলে অন্য জায়গায় পুরনো নাম থেকে যাচ্ছে।
৭.৩ 1NF (First Normal Form) — এটমিক ভ্যালু
রুলস:
- কোনো কলামে মাল্টিপল ভ্যালু (কমা দিয়ে আলাদা করা) রাখা যাবে না।
- প্রতিটি ফিল্ডে মাত্র একটি ডেটা (Atomic Value) থাকবে।
❌ সমস্যা (Not 1NF):
phone_numbers কলামে কমা দিয়ে একাধিক নম্বর রাখা হয়েছে।
| id | name | phone_numbers |
|---|---|---|
| 1 | Shagor | 01711, 01822 |
✅ সমাধান (1NF):
আলাদা টেবিল বা আলাদা রো তৈরি করতে হবে।
Table: users
| id | name |
|---|---|
| 1 | Shagor |
Table: user_phones
| id | user_id | phone |
|---|---|---|
| 10 | 1 | 01711 |
| 11 | 1 | 01822 |
৭.৪ 2NF (Second Normal Form) — কম্পোজিট কি এবং ডিপেন্ডেন্সি
রুলস:
- টেবিলকে অবশ্যই 1NF হতে হবে।
- কোনো নন-কি (Non-key) কলাম প্রাইমারি কি-এর অর্ধেক অংশের ওপর নির্ভর করতে পারবে না (Partial Dependency)।
এটি তখনই প্রযোজ্য যখন টেবিলে Composite Primary Key থাকে।
❌ সমস্যা (Not 2NF):
টেবিল: order_items | প্রাইমারি কি: (order_id, product_id)
| order_id | product_id | product_name | quantity |
|---|---|---|---|
| 101 | 5 | iPhone 14 | 1 |
এখানে product_name শুধু product_id এর ওপর নির্ভর করে, order_id এর সাথে এর কোনো সম্পর্ক নেই। এটি স্পেস নষ্ট করছে।
✅ সমাধান (2NF):
প্রোডাক্টের তথ্য আলাদা টেবিলে নিয়ে যান।
Table: products
| id | name |
|---|---|
| 5 | iPhone 14 |
Table: order_items
| order_id | product_id | quantity |
|---|---|---|
| 101 | 5 | 1 |
৭.৫ 3NF (Third Normal Form) — ট্রানজিটিভ ডিপেন্ডেন্সি
রুলস:
- টেবিলকে অবশ্যই 2NF হতে হবে।
- কোনো নন-কি কলাম অন্য কোনো নন-কি কলামের ওপর নির্ভর করতে পারবে না (Transitive Dependency)।
সহজ কথায়: "A depends on B, B depends on C" — এমন চেইন রাখা যাবে না।
❌ সমস্যা (Not 3NF):
| id | name | city | city_zip_code |
|---|---|---|---|
| 1 | Shagor | Dhaka | 1200 |
zip_code আসলে city এর ওপর নির্ভর করে, ইউজারের id এর ওপর সরাসরি নয়। ঢাকা শহর যেখানেই থাকবে, জিপ কোড ১২০০-ই হবে। বারবার জিপ কোড লেখা মানে ডুপ্লিকেশন।
✅ সমাধান (3NF):
শহরের তথ্য আলাদা করুন।
Table: cities
| id | name | zip_code |
|---|---|---|
| 1 | Dhaka | 1200 |
Table: users
| id | name | city_id |
|---|---|---|
| 1 | Shagor | 1 |
৭.৬ BCNF (Boyce-Codd Normal Form)
একে 3.5 NF বলা যেতে পারে। এটি 3NF এর চেয়েও একটু কড়া।
রুল: টেবিলের প্রতিটি নির্ণায়ক (Determinant) অবশ্যই ক্যান্ডিডেট কি (Candidate Key) হতে হবে।
সাধারণ ওয়েব অ্যাপ্লিকেশনে 3NF পর্যন্ত করাই যথেষ্ট। BCNF মূলত খুব জটিল রিলেশনের ক্ষেত্রে লাগে।
৭.৭ Denormalization — সিনিয়রিটির পরিচয়
এতক্ষণ শিখলাম টেবিল ভাঙতে হয় (Normalize)। এখন শিখব কখন জোড়া লাগাতে হয় (Denormalize)। Denormalization মানে পারফরম্যান্স বাড়ানোর জন্য ইচ্ছাকৃতভাবে কিছু ডুপ্লিকেট ডেটা রাখা।
কখন করবেন?
- যখন প্রচুর JOIN এর কারণে কুয়েরি স্লো হয়ে যাচ্ছে।
- রিপোর্টিং বা এনালিটিক্স ড্যাশবোর্ডের জন্য।
- হিস্ট্রি ঠিক রাখার জন্য।
বাস্তব উদাহরণ (E-commerce Invoice):
একজন ইউজার প্রোফাইলে তার ঠিকানা পরিবর্তন করে মিরপুর থেকে গুলশান করল। কিন্তু তার গত বছরের অর্ডারের ইনভয়েসে কি ঠিকানা বদলে গুলশান হওয়া উচিত? না! কারণ তখন সে মিরপুরেই ছিল।
তাই orders টেবিলে আমরা ইউজারের এড্রেস কপি করে রেখে দিই (Denormalize করি)।
-- orders টেবিলে address_text রাখা হলো যাতে user table join করতে না হয় এবং হিস্ট্রি ঠিক থাকে
CREATE TABLE orders (
id INT,
user_id INT,
shipping_address TEXT, -- Denormalized column
total_amount DECIMAL
);
৭.৮ Entity Relationship (ER) Diagram Basics
কোড লেখার আগে খাতা-কলমে বা টুলে (যেমন: MySQL Workbench, Draw.io) ডায়াগ্রাম আঁকা জরুরি।
সম্পর্কের ধরণ (Relationships):
- One-to-One (1:1): একজন মানুষের একটাই NID কার্ড থাকে। User ↔ UserProfile
- One-to-Many (1:N): একজন ইউজার অনেকগুলো অর্ডার দিতে পারে। User ↔ Orders (সবচেয়ে বেশি ব্যবহৃত)
- Many-to-Many (M:N): একটি প্রোডাক্ট অনেক ক্যাটাগরিতে থাকতে পারে, আবার একটি ক্যাটাগরিতে অনেক প্রোডাক্ট থাকতে পারে।
Pivot Table/Junction Table:
M:N সম্পর্ক হ্যান্ডেল করতে মাঝখানে একটি টেবিল লাগে। যেমন: product_categories (product_id, category_id)।
৭.৯ Senior-Level Database Design Rules (Checklist)
প্রজেক্ট ডিজাইনের সময় এই চেকলিস্টটি বাইবেলের মতো ফলো করবেন:
- ✓ Primary Key: সব সময় BIGINT এবং AUTO_INCREMENT ব্যবহার করুন।
- ✓ Foreign Key Indexing: রিলেশন কলামে অবশ্যই ইনডেক্স করবেন।
- ✓ Avoid Stored Lists: "01711,01922" — এভাবে ডেটা রাখবেন না।
- ✓ No Calculated Data: age কলাম রাখবেন না, date_of_birth রাখুন। (কারণ বয়স প্রতিদিন বাড়ে, কিন্তু জন্মতারিখ ফিক্সড)।
- ✓ Pivot Table for M:N: মেনি-টু-মেনি রিলেশনের জন্য অলসতা করে কমা দিয়ে আইডি রাখবেন না, আলাদা পিভট টেবিল বানান।
- ✓ Meta Columns: প্রতিটি টেবিলে created_at এবং updated_at (TIMESTAMP) রাখা স্মার্ট ডিজাইনের লক্ষণ।
- ✓ Naming Convention: সব সময় ছোট হাতের অক্ষর এবং snake_case ব্যবহার করুন (যেমন: user_details, first_name)।
❓ Interview Q&A (Database Design)
Q: Normalization কেন দরকার?
Ans: ডেটা রিডান্ডেন্সি (ডুপ্লিকেশন) কমানোর জন্য এবং ডেটা ইন্টিগ্রিটি (সততা) বজায় রাখার জন্য। এটি Update Anomaly এবং Delete Anomaly দূর করে।
Q: Denormalization কখন করবেন?
Ans: যখন রিড অপারেশন (Read Operation) অনেক বেশি হয় এবং JOIN এর কারণে সিস্টেম স্লো হয়ে যায়। বিশেষ করে রিপোর্টিং এবং হিস্ট্রি ডেটার জন্য এটি করা হয়।
Q: 2NF এবং 3NF এর মূল পার্থক্য কী?
Ans: 2NF কম্পোজিট প্রাইমারি কি-এর পার্শিয়াল ডিপেন্ডেন্সি দূর করে। আর 3NF নন-কি কলামের ট্রানজিটিভ ডিপেন্ডেন্সি (এক কলাম অন্য কলামের ওপর নির্ভরশীলতা) দূর করে।
🎯 অধ্যায় ৭ এর সারাংশ (Summary)
এই অধ্যায়ে আমরা শিখলাম:
- ✓ Design Process: Requirement → Entities → Attributes → Relationships → Normalization → ER Diagram
- ✓ 1NF: Atomic values - কোন কলামে একাধিক মান রাখা যাবে না।
- ✓ 2NF: Partial dependency দূর করা - Composite key এর অংশের ওপর নন-কি কলাম নির্ভর করতে পারে না।
- ✓ 3NF: Transitive dependency দূর করা - নন-কি কলাম অন্য নন-কি কলামের ওপর নির্ভর করতে পারে না।
- ✓ Denormalization: পারফরম্যান্সের জন্য ইচ্ছাকৃত ডুপ্লিকেশন - রিপোর্টিং এবং হিস্ট্রির জন্য।
- ✓ Relationships: 1:1, 1:N, M:N - এবং M:N এর জন্য Pivot Table প্রয়োজন।
✨ এখন আপনি জানেন কীভাবে একটি প্রফেশনাল ডেটাবেস আর্কিটেকচার দাঁড় করাতে হয়। পরবর্তী অধ্যায়ে আমরা শিখব Indexing—যেখানে আমরা শিখব কীভাবে ডেটাবেসকে রকেটের গতিতে চালানো যায়।
প্রস্তুত তো? 🚀