Normalizatsiya — 1NF, 2NF, 3NF, BCNF

~25 daq · MySQL · Ma'lumotlar Bazasini Loyihalash

Muammodan boshlaylik

Yangi dasturchi buyurtmalar uchun bitta "qulay" jadval yaratdi:

buyurtmalar_hammasi
+----+------------+-----------+--------------+------------------------------+------------+
| id | mijoz      | telefon   | shahar       | mahsulotlar                  | jami       |
+----+------------+-----------+--------------+------------------------------+------------+
| 1  | Aziz K.    | 901112233 | Toshkent     | Samsung A55 x1, Qopqoq x2    | 5040000    |
| 2  | Aziz K.    | 901112233 | Toshkent     | AirPods Pro x1               | 3100000    |
| 3  | Malika R.  | 935554433 | Samarqand    | MacBook Air x1, AirPods x1   | 20000000   |
+----+------------+-----------+--------------+------------------------------+------------+

Bir yildan keyin muammolar:

  • O'zgartirish anomaliyasi: Aziz telefonini o'zgartirdi — 47 ta qatorda yangilash kerak. Bittasi unutildi — endi Azizning ikki xil telefoni bor
  • Qo'shish anomaliyasi: yangi mijoz ro'yxatdan o'tdi, lekin hali buyurtma bermadi — uni qayerga yozish kerak? Buyurtmasiz qator yaratib bo'lmaydi
  • O'chirish anomaliyasi: Malikaning yagona buyurtmasi o'chirildi — Malika haqidagi barcha ma'lumot ham yo'qoldi
  • "AirPods necha dona sotilgan?" — mahsulotlar matnini qismlarga ajratish kerak

Normalizatsiya — jadvallarni shunday tuzishki, bu anomaliyalar umuman paydo bo'lmasin. Asosiy g'oya: har bir fakt — bitta joyda.


1NF — birinchi normal shakl

Qoida: har bir katakda — bitta, bo'linmas qiymat. Takrorlanuvchi guruhlar yo'q.

❌ mahsulotlar: "Samsung A55 x1, Qopqoq x2"          — bitta katakda ro'yxat
❌ telefon1, telefon2, telefon3                       — takrorlanuvchi ustunlar
❌ manzil: "Toshkent, Chilonzor, 9-kvartal, 12-uy"   — ehtiyojga qarab (pastga qarang)

Yechim — ro'yxatni alohida qatorlarga:

buyurtma_qatorlari
| buyurtma_id | mahsulot     | soni |
| 1           | Samsung A55  | 1    |
| 1           | Qopqoq       | 2    |
| 2           | AirPods Pro  | 1    |

Endi "AirPods necha dona sotilgan" — oddiy SUM.

[!INFO] "Bo'linmas" — ehtiyojga bog'liq. Agar siz hech qachon manzilni tuman bo'yicha qidirmasangiz — manzilni bitta VARCHAR da saqlash 1NF ni buzmaydi. Agar "Chilonzordagi mijozlar" kerak bo'lsa — shahar, tuman, kocha alohida ustunlar.


2NF — ikkinchi normal shakl

Qoida: 1NF + har bir ustun butun primary key ga bog'liq, uning bir qismiga emas.

Bu faqat composite primary key li jadvallarda muammo bo'ladi:

buyurtma_qatorlari  — PRIMARY KEY (buyurtma_id, mahsulot_id)
| buyurtma_id | mahsulot_id | soni | mahsulot_nomi | mahsulot_toifasi |
| 1           | 2           | 1    | Samsung A55   | Telefonlar       |
| 3           | 2           | 1    | Samsung A55   | Telefonlar       |
  • soni — ikkala kalitga bog'liq (qaysi buyurtmada, qaysi mahsulotdan) ✅
  • mahsulot_nomi, mahsulot_toifasi — faqat mahsulot_id ga bog'liq ❌

Mahsulot nomi har bir buyurtmada takrorlanadi. Nomini o'zgartirsangiz — hamma buyurtma qatorlarini yangilash kerak.

Yechim — qisman bog'liq ustunlarni o'z jadvaliga:

mahsulotlar:          id | nom         | toifa_id
buyurtma_qatorlari:   buyurtma_id | mahsulot_id | soni | narx

narx esa qoladi — chunki bu sotilgan paytdagi narx, ya'ni aynan shu buyurtma qatoriga tegishli fakt (18-dars).


3NF — uchinchi normal shakl

Qoida: 2NF + kalit bo'lmagan ustun boshqa kalit bo'lmagan ustunga bog'liq emas (tranzitiv bog'liqlik yo'q).

mijozlar
| id | ism    | tuman_id | tuman_nomi | shahar    |
| 1  | Aziz   | 5        | Chilonzor  | Toshkent  |
| 3  | Jasur  | 5        | Chilonzor  | Toshkent  |

Bog'liqlik zanjiri: id → tuman_id → tuman_nomi, shahar.

tuman_nomi va shahar mijozga emas, tumanga bog'liq. Tuman nomi o'zgarsa — barcha mijozlarni yangilash kerak.

Yechim:

tumanlar:  id | nom       | shahar
mijozlar:  id | ism       | tuman_id

Eslab qolish uchun: har bir kalit bo'lmagan ustun "kalitga, butun kalitga va faqat kalitga" bog'liq bo'lsin.

Shakl Qisqacha
1NF Katakda bitta qiymat, ro'yxatlar yo'q
2NF Butun kalitga bog'liq (composite key qismiga emas)
3NF Faqat kalitga bog'liq (boshqa ustun orqali emas)

BCNF — Boyce-Codd normal shakli

3NF ning qat'iyroq varianti. Qoida: har bir funksional bog'liqlikda chap tomon — kalit (yoki kalit kandidati) bo'lishi kerak.

3NF dan farqi kamdan-kam, bir nechta overlapping (ustma-ust tushuvchi) kandidat kalitlar bo'lganda seziladi:

dars_jadvali  — talaba bir fanni faqat bitta o'qituvchidan oladi,
                har bir o'qituvchi faqat bitta fanni o'qitadi
| talaba | fan       | oqituvchi |
| Ali    | Matematika| Karimov   |
| Vali   | Matematika| Karimov   |
| Ali    | Fizika    | Toshev    |

Kalit — (talaba, fan). Lekin oqituvchi → fan bog'liqligi ham bor, va oqituvchi — kalit emas. Karimov boshqa fanga o'tsa — hamma qatorlarni yangilash kerak.

Yechim:

oqituvchilar:  oqituvchi | fan
yozilishlar:   talaba    | oqituvchi

Amalda 3NF ga yetgan sxemalarning ko'pchiligi avtomatik BCNF da bo'ladi.


Dokon bazasi — normallashtirilgan

Kurs boshidan beri ishlatayotgan sxema (5-dars) — aynan shu jarayonning natijasi:

toifalar           (id, nom)
mahsulotlar        (id, toifa_id → toifalar, nom, narx, soni)
mijozlar           (id, ism, email, telefon, shahar)
buyurtmalar        (id, mijoz_id → mijozlar, holat, yaratilgan)
buyurtma_qatorlari (id, buyurtma_id → buyurtmalar, mahsulot_id → mahsulotlar, soni, narx)

Boshidagi "qulay" jadval bilan solishtiring:

  • Telefon o'zgarsa — 1 qator
  • Buyurtmasiz mijoz — muammo yo'q
  • Buyurtma o'chirilsa — mijoz qoladi
  • "AirPods necha dona" — SUM(soni) WHERE mahsulot_id = 5

Amaliy usul

Nazariy atamalarni yod olish shart emas. Loyihalashda har bir ustunga quyidagi savollarni bering:

  1. "Bu katakda bir nechta qiymat bo'lishi mumkinmi?" → ha bo'lsa, alohida jadval (1NF)
  2. "Bu qiymat jadvalning qaysi qatorlarida takrorlanadi?" → ko'p qatorda bir xil bo'lsa, u boshqa narsa haqidagi fakt — o'z jadvaliga (2NF, 3NF)
  3. "Bu qiymat o'zgarsa — nechta qatorni yangilash kerak?" → bittadan ko'p bo'lsa — normallashtiring
  4. "Bu narsani boshqa narsasiz yaratish yoki o'chirish mumkinmi?" → mijoz buyurtmasiz yashay olsa — ular alohida jadvallarda

Nima uchun shunday?

Nima uchun normalizatsiya nazariyasi 1970-yillardan beri o'zgarmagan?

Chunki u texnologiyaga emas, mantiqqa asoslangan. Edgar Codd relational modelni matematik nazariya sifatida yaratgan: jadvallar — to'plamlar, bog'liqliklar — funksiyalar. "Bitta fakt — bitta joyda" tamoyili har qanday ma'lumot tizimida to'g'ri: Excel da ham, MongoDB da ham, kod ichidagi o'zgaruvchilarda ham (DRY tamoyili). Normalizatsiya — bu tamoyilning qat'iy, tekshiriladigan shakli.


Xulosa

Eslab qoling:

  • Normalizatsiya — anomaliyalardan qochish: o'zgartirish, qo'shish, o'chirish
  • Asosiy g'oya: har bir fakt — bitta joyda
  • 1NF — katakda bitta qiymat; ro'yxatlar va telefon1, telefon2 yo'q
  • 2NF — composite key ning qismiga emas, butun kalitga bog'liq
  • 3NF — boshqa kalit bo'lmagan ustun orqali emas, faqat kalitga bog'liq
  • BCNF — har bir bog'liqlikning chap tomoni kalit
  • Amaliy test: "bu qiymat o'zgarsa, nechta qatorni yangilash kerak?"

Keyingi dars

47-dars: Denormalizatsiya — qachon va nima uchun