রিলেশনাল ডাটাবেস কী?

রিলেশনাল ডাটাবেস (RDBMS) হলো একটি ডাটাবেস ম্যানেজমেন্ট সিস্টেম যেখানে ডাটা টেবিল আকারে সংরক্ষণ করা হয় এবং টেবিলগুলোর মধ্যে রিলেশন (সম্পর্ক) থাকে। প্রতিটি টেবিলে রো (সারি/রেকর্ড) এবং কলাম (ফিল্ড/অ্যাট্রিবিউট) থাকে।

সহজ ভাষায়:
একটি এক্সেল শিটের মতো, কিন্তু অনেক বেশি শক্তিশালী। একাধিক শিটের মধ্যে সম্পর্ক তৈরি করা যায় এবং খুব জটিল প্রশ্নের উত্তর দেওয়া যায়।

┌─────────────────┐     ┌─────────────────┐
│   ইউজার টেবিল   │       │   অর্ডার টেবিল    │
├─────┬─────┬─────┤     ├─────┬─────┬─────┤
│user_id│ নাম │ শহর │    │order_id│user_id│ প্রোডাক্ট │
├─────┼─────┼─────┤     ├─────┼─────┼─────┤
│ 1   │ রহিম│ ঢাকা │      │ 101 │ 1   │ ল্যাপটপ │
│ 2   │ করিম│ চট্টগ্রাম│     │ 102 │ 1   │ মাউস │
│ 3   │ জব্বার│খুলনা │      │ 103 │ 2   │ কিবোর্ড │
└─────┴─────┴─────┘     └─────┴─────┴─────┘
                              ↑
                        (user_id = foreign key)

কেন রিলেশনাল ডাটাবেস?

সুবিধা ব্যাখ্যা
এসিড কমপ্লায়েন্স Atomicity, Consistency, Isolation, Durability – ডাটা ইন্টিগ্রিটি নিশ্চিত করে
জটিল কুয়েরি SQL দিয়ে জয়েন, সাবকুয়েরি, এগ্রিগেশন করা যায়
রেফারেন্সিয়াল ইন্টিগ্রিটি ফরেন কী দিয়ে ডাটার মধ্যে সম্পর্ক বজায় রাখে
স্ট্যান্ডার্ডাইজেশন SQL প্রায় সব জায়গায় একই রকম
মাচুরিটি ৪০+ বছর ধরে গবেষণা ও অপটিমাইজেশন

মূল ধারণাসমূহ

১. টেবিল ও স্কিমা

-- স্কিমা ডেফিনেশন (টেবিলের গঠন)
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

২. প্রাইমারি কী (Primary Key)

প্রতিটি রোকে ইউনিকভাবে চিহ্নিত করে।

প্রাইমারি কী হতে হবে:
✅ ইউনিক – কোনো ডুপ্লিকেট নেই
✅ নট নাল – সব রোতে অবশ্যই মান থাকতে হবে
✅ ইমিউটেবল – পরিবর্তন করা উচিত নয়

৩. ফরেন কী (Foreign Key)

দুটি টেবিলের মধ্যে সম্পর্ক তৈরি করে।

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

৪. ইনডেক্স (Index)

ডাটা খোঁজা দ্রুত করতে সাহায্য করে।

ইনডেক্স ছাড়া: পুরো টেবিল স্ক্যান → O(n)
ইনডেক্স দিয়ে: B-Tree অনুসন্ধান → O(log n)

উদাহরণ: ১০ মিলিয়ন রো-র টেবিলে
ইনডেক্স ছাড়া খুঁজতে → ~১০ সেকেন্ড
ইনডেক্স দিয়ে → ~০.০১ সেকেন্ড
CREATE INDEX idx_users_email ON users(email);

নরমালাইজেশন (Normalization)

ডাটা রিডান্ডেন্সি কমানোর প্রক্রিয়া।

নরমাল ফর্মসমূহ

ফর্ম নিয়ম উদাহরণ
১এনএফ প্রতিটি সেলে একটি মান থাকবে ❌ "মাউস,কিবোর্ড" → ✅ আলাদা রো
২এনএফ পার্শিয়াল ডিপেন্ডেন্সি থাকবে না (কম্পোজিট প্রাইমারি কী-র জন্য) অর্ডার টেবিলে user_id থেকে user_name না রাখা
৩এনএফ ট্রানজিটিভ ডিপেন্ডেন্সি থাকবে না user table-এ zipcode থেকে city বের করা যায় না

ডিনরমালাইজেশন কখন করবেন?

কখন কেন
পড়ার পারফরম্যান্স বাড়াতে জয়েন কমানোর জন্য
রিপোর্টিং/অ্যানালিটিক্সে অনেক জয়েন ধীর করে দেয়
ক্যাশিং হিসেবে ডাটা ফ্রিকোয়েন্টলি পড়া হয়

এসিড প্রপার্টিজ (ACID)

প্রপার্টি ব্যাখ্যা বাস্তব উদাহরণ
Atomicity সব অপারেশন সফল না হলে পুরো ট্রানজেকশন বাতিল ব্যাংক ট্রান্সফার – টাকা কাটা ও যোগ করা দুটোই হবে নয়তো কিছুই হবে না
Consistency ট্রানজেকশনের আগে-পরে ডাটাবেস কনসিস্টেন্ট থাকে প্রাইমারি কী ইউনিক থাকবেই
Isolation একসাথে চলা ট্রানজেকশন একে অপরকে প্রভাবিত করবে না দুজন একই সময়ে শেষ আসন বুক করার চেষ্টা – একজন পাবে
Durability কমিট করা ডাটা হারাবে না (ডিস্কে সেভ) বিদ্যুৎ চলে গেলেও কমিট করা লেনদেন থাকবে

আইসোলেশন লেভেল (Isolation Levels)

লেভেল ডার্টি রিড নন-রিপিটেবল রিড ফ্যান্টম রিড ফোর লকিং
READ UNCOMMITTED সম্ভব সম্ভব সম্ভব না
READ COMMITTED অসম্ভব সম্ভব সম্ভব না
REPEATABLE READ অসম্ভব অসম্ভব সম্ভব (MySQL না) না
SERIALIZABLE অসম্ভব অসম্ভব অসম্ভব হ্যাঁ
-- লেভেল সেট করা
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

BEGIN;
    SELECT balance FROM accounts WHERE user_id = 1;
    -- অন্য ট্রানজেকশন user_id 1 এর ব্যালেন্স পরিবর্তন করতে পারবে
COMMIT;

জনপ্রিয় রিলেশনাল ডাটাবেস

ডাটাবেস টাইপ স্ট্রং পয়েন্ট ব্যবহার
PostgreSQL ওপেন সোর্স JSON সাপোর্ট, এক্সটেনসিবল সাধারণ উদ্দেশ্য
MySQL ওপেন সোর্স দ্রুত রিড, জনপ্রিয় ওয়েব অ্যাপ
SQLite এম্বেডেড লাইটওয়েট, কোনো সার্ভার নেই মোবাইল, ব্রাউজার
Microsoft SQL Server কমার্শিয়াল BI টুল, .NET ইন্টিগ্রেশন এন্টারপ্রাইজ
Oracle কমার্শিয়াল পার্টিশনিং (বিল্ট-ইন) ব্যাংক, মিশন ক্রিটিক্যাল
Amazon Aurora ক্লাউড ৫× MySQL গতি, ৩× PostgreSQL গতি AWS সার্ভিস

জয়েন (JOIN) এর প্রকারভেদ

INNER JOIN:   শুধু ম্যাচিং রো
LEFT JOIN:    সব বাম টেবিল + ম্যাচিং ডান
RIGHT JOIN:   সব ডান টেবিল + ম্যাচিং বাম
FULL OUTER:   সব রো (উভয় টেবিল)
CROSS JOIN:   কার্টেসিয়ান প্রোডাক্ট
-- INNER JOIN উদাহরণ
SELECT users.name, orders.product 
FROM users 
INNER JOIN orders ON users.user_id = orders.user_id;

-- একাধিক টেবিল জয়েন
SELECT u.name, o.product, p.price
FROM users u
JOIN orders o ON u.user_id = o.user_id
JOIN products p ON o.product_id = p.product_id
WHERE o.order_date > '2024-01-01';

রিলেশনাল বনাম নোএসকিউএল ডাটাবেস

ফ্যাক্টর রিলেশনাল (SQL) নোএসকিউএল (NoSQL)
ডাটা মডেল টেবিল (স্ট্রাকচার্ড) ডকুমেন্ট, কী-ভ্যালু, গ্রাফ
স্কিমা ফিক্সড (মাইগ্রেশন দরকার) ফ্লেক্সিবল
স্কেলিং ভার্টিক্যাল (উপরের দিকে) হরাইজন্টাল (পাশের দিকে)
জয়েন শক্তিশালী দুর্বল বা নেই
এসিডি পুরো সাপোর্ট অনেকের নেই
ইউজ কেস ট্রানজেকশন, রিপোর্ট ক্যাশ, লগ, রিয়েল-টাইম
পরিণততা খুব পরিণত (৪০+ বছর) আধুনিক (১০+ বছর)

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

১. সিলেক্ট * ব্যবহার করবেন না

❌ SELECT * FROM users WHERE city = 'Dhaka';
✅ SELECT user_id, name FROM users WHERE city = 'Dhaka';

২. ইনডেক্স ব্যবহার করুন, কিন্তু অতিরিক্ত নয়

-- বারবার WHERE এ ব্যবহার হয় এমন কলামে ইনডেক্স
CREATE INDEX idx_users_city ON users(city);

-- কিন্তু ইনডেক্স বেশি হলে ইনসার্ট/আপডেট ধীর হয়

৩. কুয়েরি প্ল্যান এক্সপ্লেইন করুন

EXPLAIN SELECT * FROM users WHERE email = 'rahim@example.com';
-- দেখায় ইনডেক্স ব্যবহার করছে কিনা

৪. জয়েনের অর্ডার

  • ছোট টেবিল আগে, বড় টেবিল পরে
  • ইনডেক্সড কলামে জয়েন করুন

৫. ব্যাচ প্রসেসিং

❌ ১০০০ বার লুপ চালিয়ে UPDATE
✅ UPDATE users SET status = 'active' 
   WHERE last_login > '2024-01-01' LIMIT 1000;

কখন রিলেশনাল ডাটাবেস ব্যবহার করবেন?

করবেন:

  • ব্যাংকিং, ই-কমার্স (ট্রানজেকশন জরুরি)
  • রিপোর্টিং, BI (জটিল কুয়েরি লাগে)
  • যেখানে ডাটার গঠন পরিষ্কার ও স্টেবল
  • ডাটা ইন্টিগ্রিটি খুব গুরুত্বপূর্ণ
  • শত শত টেরাবাইটের কম ডাটা

করবেন না:

  • খুব বড় ডাটা (পেটাবাইট) → ডাটা ওয়্যারহাউস লাগে
  • লেখা অনেক বেশি (মিলিয়ন/সেকেন্ড) → NoSQL ভালো
  • ডাটার ধরন প্রায়ই বদলায় → স্কিমালেস NoSQL
  • ফুল টেক্সট সার্চ দরকার → Elastisearch ভালো

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

সমস্যা কারণ সমাধান
ধীর কুয়েরি ইনডেক্স নেই, পুরো টেবিল স্ক্যান EXPLAIN করে দেখুন, ইনডেক্স যোগ করুন
ডেডলক দুই ট্রানজেকশন একে অপরের জন্য অপেক্ষা লকের অর্ডার ঠিক করুন, Retry লজিক যোগ করুন
কানেকশন লিক কানেকশন বন্ধ করা হয়নি কানেকশন পুল ব্যবহার করুন, defer/finally-এ ক্লোজ করুন
ব্লোটেড টেবিল ডিলিট হলেও জায়গা ফেরত যায় না VACUUM (PostgreSQL) বা OPTIMIZE (MySQL) চালান

চিটশিট: দরকারি SQL কমান্ড

-- ক্রিয়েট
CREATE DATABASE mydb;
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));

-- ইনসার্ট
INSERT INTO users (id, name) VALUES (1, 'রহিম');
INSERT INTO users (id, name) VALUES (2, 'করিম'), (3, 'জব্বার');

-- সিলেক্ট
SELECT * FROM users WHERE id = 1;
SELECT COUNT(*) FROM users;

-- আপডেট
UPDATE users SET name = 'রহিমুদ্দিন' WHERE id = 1;

-- ডিলিট
DELETE FROM users WHERE id = 3;

-- এগ্রিগেশন
SELECT city, COUNT(*) FROM users GROUP BY city;
SELECT city, AVG(age) FROM users GROUP BY city HAVING AVG(age) > 25;

-- সাবকুয়েরি
SELECT name FROM users 
WHERE user_id IN (SELECT user_id FROM orders WHERE amount > 1000);
Share