Database Normalization কী?

Normalization হলো ডেটাবেজ ডিজাইনের একটি পদ্ধতি যেখানে টেবিলগুলোকে সুনির্দিষ্ট নিয়ম মেনে সংগঠিত করা হয়। এর মূল উদ্দেশ্য হলো Data Redundancy কমানো এবং Data Integrity নিশ্চিত করা।


Normalization কেন দরকার?

Unnormalized টেবিলের সমস্যা:

-- সমস্যাযুক্ত টেবিল (Unnormalized)
orders:
| order_id | customer_name | customer_email  | product_name | product_price | quantity |
|----------|---------------|-----------------|--------------|---------------|---------|
| 1        | Rahim         | rahim@test.com  | Laptop       | 50000         | 1       |
| 2        | Rahim         | rahim@test.com  | Mouse        | 500           | 2       |
| 3        | Karim         | karim@test.com  | Laptop       | 50000         | 1       |

সমস্যা:

  • Rahim-এর email দুইবার আছে (Redundancy)
  • Laptop-এর price দুইবার আছে (Redundancy)
  • Email পরিবর্তন করলে দুই জায়গায় করতে হবে (Update Anomaly)
  • একজন Customer-এর শেষ Order মুছলে Customer-ও হারিয়ে যায় (Delete Anomaly)

Normal Forms

1NF (First Normal Form)

নিয়ম: প্রতিটি কলামে একটিমাত্র Atomic মান থাকবে, কোনো Repeating Group থাকবে না।

-- ❌ 1NF লঙ্ঘন
customers:
| id | name  | phone_numbers              |
|----|-------|---------------------------|
| 1  | Rahim | 01700, 01800               |  -- দুটি phone একটি কলামে!

-- ✅ 1NF সঠিক
customer_phones:
| customer_id | phone_number |
|-------------|-------------|
| 1           | 01700       |
| 1           | 01800       |

2NF (Second Normal Form)

নিয়ম: 1NF মানতে হবে + প্রতিটি non-key কলাম পুরো Primary Key-এর উপর নির্ভরশীল হবে (Partial Dependency নেই)।

-- ❌ 2NF লঙ্ঘন (Composite PK: order_id + product_id)
order_items:
| order_id | product_id | quantity | product_name | product_price |
|----------|------------|---------|--------------|---------------|
| 1        | 101        | 2       | Laptop       | 50000         |
-- product_name, product_price শুধু product_id এর উপর নির্ভরশীল (Partial Dependency)

-- ✅ 2NF সঠিক: আলাদা টেবিল করুন
order_items:
| order_id | product_id | quantity |

products:
| product_id | product_name | product_price |

3NF (Third Normal Form)

নিয়ম: 2NF মানতে হবে + কোনো Transitive Dependency থাকবে না।

-- ❌ 3NF লঙ্ঘন
employees:
| emp_id | name  | dept_id | dept_name | dept_location |
|--------|-------|---------|-----------|---------------|
-- dept_name, dept_location → dept_id এর উপর নির্ভরশীল (Transitive)
-- emp_id → dept_id → dept_name (পরোক্ষ নির্ভরশীলতা)

-- ✅ 3NF সঠিক
employees:
| emp_id | name  | dept_id |

departments:
| dept_id | dept_name | dept_location |

BCNF (Boyce-Codd Normal Form)

নিয়ম: 3NF-এর কঠোর রূপ। প্রতিটি Determinant একটি Candidate Key হতে হবে।


বাস্তব Normalization উদাহরণ

Unnormalized → 3NF পর্যন্ত

-- ধাপ ১: Unnormalized
orders:
| order_id | customer_name | customer_email | product_name | product_price | qty |

-- ধাপ ২: 1NF (Atomic values নিশ্চিত)
orders: | order_id | customer_id | product_id | qty |
(প্রতিটি কলামে একটিমাত্র মান)

-- ধাপ ৩: 2NF (Partial Dependency দূর)
orders:    | order_id | customer_id | order_date |
order_items: | order_id | product_id | qty |
customers: | customer_id | customer_name | customer_email |
products:  | product_id | product_name | product_price |

-- ধাপ ৪: 3NF (Transitive Dependency দূর) — ইতিমধ্যে 3NF অর্জিত!

JPA Entity-তে Normalized Design

@Entity
@Table(name = "customers")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;

    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
    private List<Order> orders;
}

@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private double price;
}

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;

    @Column(name = "order_date")
    private LocalDateTime orderDate;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems;
}

@Entity
@Table(name = "order_items")
public class OrderItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;

    @ManyToOne
    @JoinColumn(name = "product_id")
    private Product product;

    private int quantity;
}

Normalization এর সুবিধা ও অসুবিধা

সুবিধা:

  • Data Redundancy কম
  • Data Integrity উন্নত
  • Update Anomaly কম
  • Storage কম লাগে

অসুবিধা:

  • বেশি JOIN দরকার হয় → Query জটিল
  • অনেক সময় Performance কমে
  • বড় Application-এ Query লেখা কঠিন হয়

Denormalization কখন করবেন?

Performance-এর জন্য কখনো কখনো Intentionally Redundancy রাখা হয়। যেমন — Reporting, Analytics বা Read-heavy অ্যাপ্লিকেশনে।


সংক্ষেপে

Normal Form নিয়ম
1NF Atomic values, No repeating groups
2NF 1NF + No Partial Dependency
3NF 2NF + No Transitive Dependency
BCNF 3NF + Every determinant is a candidate key

উপসংহার

Normalization ভালো ডেটাবেজ ডিজাইনের ভিত্তি। 3NF পর্যন্ত Normalization করলে বেশিরভাগ Data Anomaly দূর হয়। তবে শুধু Performance-এর কথা মাথায় রাখলে মাঝে মাঝে সীমিত Denormalization প্রয়োজন হতে পারে। Spring Boot JPA Entity ডিজাইনেও Normalization নীতি মেনে চললে কোড আরও পরিষ্কার ও রক্ষণাবেক্ষণযোগ্য হয়।

Share