IlmHamroh
Python kursi/Bazalar va ORM12/12-dars18 daqiqa
Mundarija (22)

23.12-dars: Baza dizayni tamoyillari

23-QISM — BAZALAR VA ORM · 12-dars (yakuniy)


1. Kirish va motivatsiya

23-qism davomida SQL (23.1–23.5), ORM (23.6–23.9), kesh 23.10-bob, NoSQL 23.11-bob'ni ko'rdik. Endi eng muhim savol: jadvallarni qanday loyihalash kerak? Yomon dizayn — ma'lumot takrori (bir narsa ko'p joyda), nomuvofiqlik (bir joyda yangilandi, boshqasida yo'q), kengaytirish qiyinligi. Yaxshi dizayn — har fakt bir joyda, bog'lanishlar aniq, o'sishga tayyor.

Baza dizayni — ma'lumotni jadvallar (yoki hujjatlar) va bog'lanishlarga to'g'ri taqsimlash. Asosiy tamoyillar: normalizatsiya (takrorni yo'qotish — har fakt bir marta), kalitlar (birlamchi — noyob shaxs, tashqi — bog'lanish), cheklovlar (NOT NULL, UNIQUE, FK — baza to'g'riligini himoya qiladi), bog'lanish turlari (bir-bir, bir-ko'p, ko'p-ko'p). Bu 23.1–23.2 (jadval, JOIN) ustida quriladi.

Real vaziyat. Bir loyiha buyurtmalarni bir jadvalda saqlardi — har qatorda mijoz nomi, manzili, telefoni takrorlanardi. Mijoz manzilini o'zgartirsa, yuzlab qatorni yangilash kerak edi (ba'zisi unutildi — nomuvofiqlik). Normalizatsiya qilindi: mijoz alohida jadval, buyurtma unga havola (FK). Mijoz bir joyda — bir marta yangilanadi. Ma'lumot toza va ishonchli bo'ldi.

Bu darsda — 23-qism yakuni — baza dizayni tamoyillarini o'rganamiz.

Bu darsda:

  • Normalizatsiya nima
  • Kalitlar (birlamchi, tashqi)
  • Cheklovlar (NOT NULL, UNIQUE, FK)
  • Bog'lanish turlari (1-1, 1-ko'p, ko'p-ko'p)
  • Denormalizatsiya (qachan)
  • Dizayn jarayoni
  • 23-qism yakuni
  • Amaliy: sxema loyihalash

ℹ Misollarda sqlite3 (o'rnatilgan) bilan sinaladi.


2. Nazariya — chuqur tushuntirish

2.1. Normalizatsiya nima

Normalizatsiya — ma'lumot takrorini yo'qotish:

Yomon (takror):
  buyurtma(id, mahsulot, mijoz_nom, mijoz_manzil, mijoz_tel)
  → mijoz ma'lumoti har buyurtmada takror

Yaxshi (normallashtirilgan):
  mijoz(id, nom, manzil, tel)
  buyurtma(id, mahsulot, mijoz_id → mijoz)
  → mijoz bir marta, buyurtma havola qiladi

Normalizatsiya — ma'lumotni shunday tashkil qilishki, har fakt bir marta saqlansin (takror yo'q). Takror yomon: joy isrofi, nomuvofiqlik (bir joyda yangilandi, boshqasida yo'q). Yechim: takrorlanadigan ma'lumotni alohida jadvalga chiqar, havola (FK) bilan bog'la. "Har fakt bir joyda, bir marta".

2.2. Normal shakllar (1NF, 2NF, 3NF)

Normalizatsiya bosqichlari:

Shakl Qoida
1NF Har katak — bitta qiymat (massiv emas)
2NF 1NF + har ustun to'liq kalitga bog'liq
3NF 2NF + ustun faqat kalitga (boshqa ustunga emas)

Normal shakllar — normalizatsiya darajalari: 1NF (har katak bitta qiymat — takrorlanadigan guruh yo'q), 2NF (har ustun butun birlamchi kalitga bog'liq), 3NF (ustun faqat kalitga bog'liq, boshqa ustunga emas). Amaliyotda 3NF yetarli (ko'p loyiha). Maqsad: takror va anomaliya (yangilash muammosi) yo'q.

2.3. Kalitlar (birlamchi, tashqi)

Kalitlar — jadvallarni bog'laydi:

sql
CREATE TABLE muallif (
    id INTEGER PRIMARY KEY,       -- birlamchi kalit (noyob)
    nom TEXT NOT NULL
);
CREATE TABLE kurs (
    id INTEGER PRIMARY KEY,       -- birlamchi kalit
    nom TEXT NOT NULL,
    muallif_id INTEGER REFERENCES muallif(id)   -- tashqi kalit
);

Birlamchi kalit (primary key) — har satrni noyob aniqlaydi (odatda id, avtomatik). Tashqi kalit (foreign key) — boshqa jadval birlamchi kalitiga havola (bog'lanish). muallif_id — qaysi muallif (23.2 JOIN shu bilan). Kalit — dizayn asosi: birlamchi (shaxs), tashqi (bog'lanish).

2.4. Cheklovlar (NOT NULL, UNIQUE, FK)

Cheklovlar — baza to'g'riligini himoya qiladi:

sql
email TEXT UNIQUE NOT NULL       -- bo'sh emas, takrorlanmas
narx INTEGER CHECK (narx >= 0)   -- shart
muallif_id REFERENCES muallif(id) -- mavjud muallif

Cheklovlar — baza darajasida qoidalar: NOT NULL (bo'sh bo'lmasin), UNIQUE (takrorlanmasin — email), CHECK (shart — narx ≥ 0), FK (havola mavjud bo'lsin — yo'q muallifga bog'lab bo'lmaydi). Bu ma'lumot to'g'riligini (integrity) kafolatlaydi — dastur xatosi ham bazani buzolmaydi. "Baza o'zi himoyalanadi".

2.5. Bog'lanish turlari (1-1, 1-ko'p, ko'p-ko'p)

Uch bog'lanish turi:

Tur Misol Amalga oshirish
Bir-bir foydalanuvchi ↔ profil FK (bir tomonda)
Bir-ko'p muallif → kurslar FK (ko'p tomonda)
Ko'p-ko'p kurs ↔ teglar Oraliq jadval

Bog'lanish turlari: bir-bir (foydalanuvchi-profil — FK bir tomonda), bir-ko'p (muallif-kurslar — FK "ko'p" tomonda, eng keng tarqalgan), ko'p-ko'p (kurs-teglar — bir kurs ko'p teg, bir teg ko'p kurs — oraliq jadval kurs_teg(kurs_id, teg_id) kerak). Ko'p-ko'p to'g'ridan-to'g'ri bo'lmaydi — oraliq jadval (junction).

2.6. Denormalizatsiya (qachan)

Ba'zan takror ataylab qo'shiladi:

Normalizatsiya: har fakt bir joyda (o'qish — JOIN kerak)
Denormalizatsiya: takror qo'sh (o'qish tez, JOIN'siz)
   → masalan: kurs jadvalida "muallif_nomi" (havola + nusxa)
   → tez o'qish, lekin yangilash qiyin (ikki joyda)

Denormalizatsiya — unumdorlik uchun ataylab takror qo'shish (normalizatsiyaning teskarisi). Sabab: JOIN sekin 23.2-bob — takror bilan JOIN'siz o'qish tez. Narx: yangilash qiyin (takrorni sinxron ushlash). Qoida: avval normalizatsiya, keyin (o'lchab) kerak bo'lsa denormalizatsiya. NoSQL 23.11-bob ko'pincha denormallashtirilgan (ichma-ich).

2.7. Dizayn jarayoni

Sxema loyihalash qadamlari:

1. Entitylarni aniqla (foydalanuvchi, kurs, buyurtma)
2. Har entity — jadval (id + maydonlar)
3. Bog'lanishlarni top (1-ko'p, ko'p-ko'p)
4. Kalitlar (birlamchi, tashqi)
5. Cheklovlar (NOT NULL, UNIQUE, CHECK)
6. Normalizatsiya (takrorni yo'qot)
7. Indekslar (23.3 — tez-tez so'raladigan)

Dizayn jarayoni: entity (obyekt — foydalanuvchi, kurs) → jadval → bog'lanish (1-ko'p, ko'p-ko'p) → kalit (birlamchi, tashqi) → cheklov (NOT NULL, UNIQUE) → normalizatsiya (takror yo'q) → indeks 23.3-bob. Avval qog'ozda (yoki diagramma — ER), keyin SQL. Dizayn — kod yozishdan oldin (o'zgartirish qimmat).

2.8. Yaxshi dizayn belgilari

Belgi Tavsif
Har fakt bir joyda Takror yo'q (normalizatsiya)
Bog'lanish aniq FK bilan
Baza o'zi himoyalanadi Cheklovlar
Kengaytirish oson Yangi jadval/ustun
So'rov samarali Indeks, to'g'ri tuzilma

Yaxshi dizayn: har fakt bir joyda (takror yo'q), bog'lanishlar aniq (FK), baza o'zi himoyalanadi (cheklov), kengaytirish oson (yangi jadval qo'shish — eskini buzmasdan), so'rov samarali (indeks). Yomon dizaynni keyinchalik tuzatish juda qiyin (ma'lumot ko'chirish, kod o'zgarish). "Dizaynga vaqt sarfla — keyin tejaladi".


3. Tez ma'lumotnoma

sql
-- birlamchi + tashqi kalit:
CREATE TABLE muallif (id INTEGER PRIMARY KEY, nom TEXT NOT NULL);
CREATE TABLE kurs (
    id INTEGER PRIMARY KEY,
    nom TEXT NOT NULL,
    narx INTEGER CHECK (narx >= 0),
    muallif_id INTEGER REFERENCES muallif(id)   -- bir-ko'p
);

-- ko'p-ko'p (oraliq jadval):
CREATE TABLE kurs_teg (
    kurs_id INTEGER REFERENCES kurs(id),
    teg_id INTEGER REFERENCES teg(id),
    PRIMARY KEY (kurs_id, teg_id)
);

-- UNIQUE:
email TEXT UNIQUE NOT NULL

Dizayn tamoyillari

Normalizatsiya: har fakt bir marta · Kalit: birlamchi (shaxs), tashqi (bog'lanish)
Cheklov: NOT NULL/UNIQUE/CHECK/FK (himoya) · Bog'lanish: 1-1, 1-ko'p, ko'p-ko'p
Denormalizatsiya: o'lchab, kerak bo'lsa · Indeks: tez-tez so'raladigan

4. Batafsil misollar

Misollarda sqlite3 (o'rnatilgan) bilan sinaladi. PRAGMA foreign_keys=ON — SQLite'da FK cheklovini yoqadi.

Misol 1 — Normalizatsiya (takrorni yo'qotish)

python
"""normalizatsiya: takrorli (mijoz har buyurtmada) vs normallashtirilgan (mijoz alohida + FK)."""

import sqlite3


def main() -> None:
    c = sqlite3.connect(":memory:")

    print("=== 1. Yomon: takrorli dizayn ===")
    c.execute("CREATE TABLE buyurtma_yomon (id INTEGER PRIMARY KEY, mahsulot TEXT, mijoz_nom TEXT, mijoz_tel TEXT)")
    c.execute("INSERT INTO buyurtma_yomon(mahsulot,mijoz_nom,mijoz_tel) VALUES('Python','Ali','111'),('Go','Ali','111')")
    r = c.execute("SELECT mahsulot, mijoz_nom FROM buyurtma_yomon").fetchall()
    print(f"  {r}")
    print("  ⚠️ Ali ma'lumoti har qatorda takror (tel o'zgarsa — ikki joyda)")

    print("\n=== 2. Yaxshi: normallashtirilgan ===")
    c.execute("CREATE TABLE mijoz (id INTEGER PRIMARY KEY, nom TEXT NOT NULL, tel TEXT)")
    c.execute("CREATE TABLE buyurtma (id INTEGER PRIMARY KEY, mahsulot TEXT, mijoz_id INTEGER REFERENCES mijoz(id))")
    c.execute("INSERT INTO mijoz(nom,tel) VALUES('Ali','111')")
    c.execute("INSERT INTO buyurtma(mahsulot,mijoz_id) VALUES('Python',1),('Go',1)")
    print("  mijoz bir marta, buyurtma havola qiladi (FK)")

    print("\n=== 3. JOIN bilan birlashtirish ===")
    r = c.execute("""SELECT b.mahsulot, m.nom, m.tel FROM buyurtma b
                     JOIN mijoz m ON b.mijoz_id = m.id ORDER BY b.mahsulot""").fetchall()
    print(f"  {r}")

    print("\n=== 4. Yangilash (bir joyda) ===")
    c.execute("UPDATE mijoz SET tel='222' WHERE id=1")   # bir marta
    r = c.execute("SELECT DISTINCT m.tel FROM buyurtma b JOIN mijoz m ON b.mijoz_id=m.id").fetchall()
    print(f"  yangi tel (barcha buyurtmada): {r[0][0]}")
    print("  ⭐ normalizatsiya — mijoz bir joyda, bir marta yangilanadi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Yomon: takrorli dizayn ===
  [('Python', 'Ali'), ('Go', 'Ali')]
  ⚠️ Ali ma'lumoti har qatorda takror (tel o'zgarsa — ikki joyda)

=== 2. Yaxshi: normallashtirilgan ===
  mijoz bir marta, buyurtma havola qiladi (FK)

=== 3. JOIN bilan birlashtirish ===
  [('Go', 'Ali', '111'), ('Python', 'Ali', '111')]

=== 4. Yangilash (bir joyda) ===
  yangi tel (barcha buyurtmada): 222
  ⭐ normalizatsiya — mijoz bir joyda, bir marta yangilanadi

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Cheklovlar (himoya)

python
"""cheklovlar: FK (mavjud havola), UNIQUE (takrorsiz), NOT NULL, CHECK — baza to'g'riligi."""

import sqlite3


def main() -> None:
    c = sqlite3.connect(":memory:")
    c.execute("PRAGMA foreign_keys=ON")
    c.execute("CREATE TABLE muallif (id INTEGER PRIMARY KEY, nom TEXT NOT NULL)")
    c.execute("CREATE TABLE kurs (id INTEGER PRIMARY KEY, nom TEXT NOT NULL, narx INTEGER CHECK(narx>=0), muallif_id INTEGER REFERENCES muallif(id))")
    c.execute("INSERT INTO muallif(nom) VALUES('Ali')")

    print("=== 1. FK cheklovi (mavjud muallif) ===")
    c.execute("INSERT INTO kurs(nom,narx,muallif_id) VALUES('Python',100,1)")
    try:
        c.execute("INSERT INTO kurs(nom,narx,muallif_id) VALUES('X',100,99)")   # yo'q muallif
        print("  qabul qilindi (yomon)")
    except sqlite3.IntegrityError:
        print("  ⚠️ yo'q muallifga bog'lash BLOKLANDI (yaxshi)")

    print("\n=== 2. CHECK cheklovi (narx >= 0) ===")
    try:
        c.execute("INSERT INTO kurs(nom,narx,muallif_id) VALUES('Y',-50,1)")
        print("  manfiy narx qabul (yomon)")
    except sqlite3.IntegrityError:
        print("  ⚠️ manfiy narx BLOKLANDI (yaxshi)")

    print("\n=== 3. UNIQUE cheklovi (email) ===")
    c.execute("CREATE TABLE foydalanuvchi (id INTEGER PRIMARY KEY, email TEXT UNIQUE NOT NULL)")
    c.execute("INSERT INTO foydalanuvchi(email) VALUES('a@x.uz')")
    try:
        c.execute("INSERT INTO foydalanuvchi(email) VALUES('a@x.uz')")   # takror
        print("  takror email qabul (yomon)")
    except sqlite3.IntegrityError:
        print("  ⚠️ takror email BLOKLANDI (yaxshi)")

    print("\n=== 4. NOT NULL cheklovi ===")
    try:
        c.execute("INSERT INTO muallif(nom) VALUES(NULL)")
        print("  NULL nom qabul (yomon)")
    except sqlite3.IntegrityError:
        print("  ⚠️ NULL nom BLOKLANDI (yaxshi)")
    print("  ⭐ cheklovlar — baza o'zi to'g'rilikni himoya qiladi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. FK cheklovi (mavjud muallif) ===
  ⚠️ yo'q muallifga bog'lash BLOKLANDI (yaxshi)

=== 2. CHECK cheklovi (narx >= 0) ===
  ⚠️ manfiy narx BLOKLANDI (yaxshi)

=== 3. UNIQUE cheklovi (email) ===
  ⚠️ takror email BLOKLANDI (yaxshi)

=== 4. NOT NULL cheklovi ===
  ⚠️ NULL nom BLOKLANDI (yaxshi)
  ⭐ cheklovlar — baza o'zi to'g'rilikni himoya qiladi

Nima ko'rsatdi: 2.4-bo'lim.

Misol 3 — Ko'p-ko'p bog'lanish (oraliq jadval)

python
"""ko'p-ko'p: kurs ↔ teg (bir kurs ko'p teg, bir teg ko'p kurs) — oraliq jadval bilan."""

import sqlite3


def main() -> None:
    c = sqlite3.connect(":memory:")
    c.execute("CREATE TABLE kurs (id INTEGER PRIMARY KEY, nom TEXT)")
    c.execute("CREATE TABLE teg (id INTEGER PRIMARY KEY, nom TEXT)")
    # oraliq jadval (junction) — ko'p-ko'p
    c.execute("CREATE TABLE kurs_teg (kurs_id INTEGER, teg_id INTEGER, PRIMARY KEY(kurs_id, teg_id))")

    c.execute("INSERT INTO kurs(nom) VALUES('Python'),('Go')")
    c.execute("INSERT INTO teg(nom) VALUES('backend'),('data'),('system')")
    # Python: backend+data; Go: backend+system
    c.execute("INSERT INTO kurs_teg VALUES(1,1),(1,2),(2,1),(2,3)")

    print("=== 1. Kurs → teglari ===")
    r = c.execute("""SELECT k.nom, t.nom FROM kurs_teg kt
                     JOIN kurs k ON kt.kurs_id=k.id JOIN teg t ON kt.teg_id=t.id
                     WHERE k.nom='Python' ORDER BY t.nom""").fetchall()
    print(f"  Python teglari: {[x[1] for x in r]}")

    print("\n=== 2. Teg → kurslari ===")
    r = c.execute("""SELECT k.nom FROM kurs_teg kt JOIN kurs k ON kt.kurs_id=k.id
                     JOIN teg t ON kt.teg_id=t.id WHERE t.nom='backend' ORDER BY k.nom""").fetchall()
    print(f"  backend kurslari: {[x[0] for x in r]}")

    print("\n=== 3. Teg bo'yicha kurslar soni ===")
    r = c.execute("""SELECT t.nom, COUNT(*) FROM kurs_teg kt JOIN teg t ON kt.teg_id=t.id
                     GROUP BY t.nom ORDER BY t.nom""").fetchall()
    print(f"  {r}")

    print("\n=== 4. Xulosa ===")
    print("  bir kurs — ko'p teg, bir teg — ko'p kurs")
    print("  ⭐ ko'p-ko'p — oraliq jadval (kurs_teg) bilan")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Kurs → teglari ===
  Python teglari: ['backend', 'data']

=== 2. Teg → kurslari ===
  backend kurslari: ['Go', 'Python']

=== 3. Teg bo'yicha kurslar soni ===
  [('backend', 2), ('data', 1), ('system', 1)]

=== 4. Xulosa ===
  bir kurs — ko'p teg, bir teg — ko'p kurs
  ⭐ ko'p-ko'p — oraliq jadval (kurs_teg) bilan

Nima ko'rsatdi: 2.5-bo'lim.

Misol 4 — Amaliy: to'liq sxema loyihalash

Real dizayn: entitylar, bog'lanishlar, kalitlar, cheklovlar — to'liq sxema. Bu — baza loyihalashning namunasi.

python
"""to'liq sxema: foydalanuvchi, kurs, buyurtma (1-ko'p, cheklov) — dizayn jarayoni."""

import sqlite3


def main() -> None:
    c = sqlite3.connect(":memory:")
    c.execute("PRAGMA foreign_keys=ON")

    print("=== 1. Sxema loyihalash (entity + bog'lanish) ===")
    c.executescript("""
        CREATE TABLE foydalanuvchi (
            id INTEGER PRIMARY KEY,
            email TEXT UNIQUE NOT NULL,
            nom TEXT NOT NULL
        );
        CREATE TABLE kurs (
            id INTEGER PRIMARY KEY,
            nom TEXT NOT NULL,
            narx INTEGER NOT NULL CHECK (narx >= 0)
        );
        CREATE TABLE buyurtma (
            id INTEGER PRIMARY KEY,
            foydalanuvchi_id INTEGER NOT NULL REFERENCES foydalanuvchi(id),
            kurs_id INTEGER NOT NULL REFERENCES kurs(id),
            sana TEXT NOT NULL
        );
    """)
    print("  3 jadval: foydalanuvchi, kurs, buyurtma (FK bilan)")

    print("\n=== 2. Ma'lumot (cheklovlarga mos) ===")
    c.execute("INSERT INTO foydalanuvchi(email,nom) VALUES('ali@x.uz','Ali')")
    c.execute("INSERT INTO kurs(nom,narx) VALUES('Python',100),('Go',120)")
    c.execute("INSERT INTO buyurtma(foydalanuvchi_id,kurs_id,sana) VALUES(1,1,'2024-01'),(1,2,'2024-02')")
    print("  1 foydalanuvchi, 2 kurs, 2 buyurtma")

    print("\n=== 3. Hisobot (JOIN — 3 jadval) ===")
    r = c.execute("""SELECT f.nom, k.nom, k.narx FROM buyurtma b
                     JOIN foydalanuvchi f ON b.foydalanuvchi_id=f.id
                     JOIN kurs k ON b.kurs_id=k.id ORDER BY k.nom""").fetchall()
    for nom, kurs, narx in r:
        print(f"  {nom} → {kurs} ({narx})")

    print("\n=== 4. Umumiy xarid (agregat) ===")
    r = c.execute("""SELECT f.nom, SUM(k.narx) FROM buyurtma b
                     JOIN foydalanuvchi f ON b.foydalanuvchi_id=f.id
                     JOIN kurs k ON b.kurs_id=k.id GROUP BY f.nom""").fetchone()
    print(f"  {r[0]} jami xaridi: {r[1]}")
    print("  ⭐ dizayn: entity → jadval → FK → cheklov → so'rov")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Sxema loyihalash (entity + bog'lanish) ===
  3 jadval: foydalanuvchi, kurs, buyurtma (FK bilan)

=== 2. Ma'lumot (cheklovlarga mos) ===
  1 foydalanuvchi, 2 kurs, 2 buyurtma

=== 3. Hisobot (JOIN — 3 jadval) ===
  Ali → Go (120)
  Ali → Python (100)

=== 4. Umumiy xarid (agregat) ===
  Ali jami xaridi: 220
  ⭐ dizayn: entity → jadval → FK → cheklov → so'rov

Nima ko'rsatdi: 2.1–2.8-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Hammani bir jadvalda" Normalizatsiya (bo'l)
"Takror muammo emas" Nomuvofiqlik xavfi
"FK keraksiz" To'g'rilik himoyasi
"Ko'p-ko'p to'g'ridan" Oraliq jadval kerak
"Cheklov sekinlashtiradi" To'g'rilik muhimroq
"Denormalizatsiya yomon" O'lchab, kerak bo'lsa
"Dizayn keyin tuzatiladi" Keyinchalik juda qiyin
"3NF dan yuqori shart" 3NF ko'p loyihaga yetarli

6. Keng tarqalgan xatolar va yechimlari

1. Takrorli ma'lumot (normalizatsiyasiz)

sql
buyurtma(mahsulot, mijoz_nom, mijoz_tel)   -- ⚠️ takror
mijoz(...) + buyurtma(mijoz_id)            -- ✅ (FK)

2. Birlamchi kalitsiz jadval

sql
CREATE TABLE kurs (nom TEXT, narx INTEGER)   -- ⚠️ shaxs yo'q
CREATE TABLE kurs (id INTEGER PRIMARY KEY, ...)  -- ✅

3. FK cheklovsiz bog'lanish

sql
muallif_id INTEGER                          -- ⚠️ yo'q muallifga bog'lab bo'ladi
muallif_id INTEGER REFERENCES muallif(id)   -- ✅

4. Ko'p-ko'pni bir jadvalda (vergul bilan)

sql
kurs(teglar TEXT)  -- "backend,data"        -- ⚠️ so'rov qiyin
kurs_teg(kurs_id, teg_id)                    -- ✅ (oraliq)

5. UNIQUE kerak joyda yo'q

sql
email TEXT                                   -- ⚠️ takror mumkin
email TEXT UNIQUE NOT NULL                   -- ✅

6. Erta denormalizatsiya (o'lchamasdan)

sql
-- "tez bo'ladi" deb takror qo'shish         -- ⚠️ murakkablik
-- avval normalizatsiya, o'lcha, keyin        -- ✅

7. Indekssiz FK (23.3)

sql
-- FK ustuni tez-tez JOIN'da, indekssiz      -- ⚠️ sekin
CREATE INDEX ix_kurs_muallif ON kurs(muallif_id)  -- ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 23.1-dars (o'tilgan): SQL — jadval yaratish
  • 23.2-dars (o'tilgan): JOIN — bog'lanish o'qish
  • 23.3-dars (o'tilgan): Indekslar — FK indeksi
  • 23.7-dars (o'tilgan): ORM — model = jadval dizayni
  • 24-qism: Test — sxema test'da

8. Eng yaxshi amaliyotlar

  1. Normalizatsiya (3NF) — takrorni yo'qot.

  2. Har jadvalda birlamchi kalit (id).

  3. Bog'lanish — FK cheklovi bilan.

  4. Ko'p-ko'p — oraliq jadval.

  5. Cheklovlar (NOT NULL, UNIQUE, CHECK) — himoya.

  6. Denormalizatsiya — faqat o'lchab, kerak bo'lsa.

  7. FK ustunga indeks 23.3-bob.

  8. Dizaynni kod'dan oldin (ER diagramma).


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # Normalizatsiya nima?
2.  # nega takror yomon?
3.  # birlamchi kalit nima?
4.  # tashqi kalit nima?
5.  # NOT NULL nima?
6.  # UNIQUE nima?
7.  # FK cheklovi nima?
8.  # bir-ko'p nima?
9.  # ko'p-ko'p qanday?
10. # denormalizatsiya nima?
11. # 3NF nima?
12. # dizayn qachon?
Javoblar
  1. Ma'lumot takrorini yo'qotish (har fakt bir marta)
  2. Nomuvofiqlik (bir joyda yangilandi, boshqasida yo'q)
  3. Satrni noyob aniqlovchi (id)
  4. Boshqa jadvalga havola (bog'lanish)
  5. Bo'sh bo'lmasin
  6. Takrorlanmasin
  7. Havola mavjud bo'lsin
  8. Bir muallif — ko'p kurs (FK ko'p tomonda)
  9. Oraliq jadval bilan
  10. Ataylab takror (unumdorlik uchun)
  11. Ustun faqat kalitga bog'liq
  12. Kod'dan oldin (o'zgartirish qimmat)

Vazifa 2: Xatolarni tuzating

sql
1.  buyurtma(mahsulot, mijoz_nom, mijoz_tel)   -- normalizatsiya

2.  CREATE TABLE kurs (nom TEXT, narx INTEGER)  -- id

3.  muallif_id INTEGER                          -- REFERENCES

4.  kurs(teglar TEXT)  -- "backend,data"        -- oraliq

5.  email TEXT                                   -- UNIQUE
Javoblar
sql
1.  mijoz(...) + buyurtma(mijoz_id REFERENCES mijoz(id))

2.  CREATE TABLE kurs (id INTEGER PRIMARY KEY, nom TEXT, narx INTEGER)

3.  muallif_id INTEGER REFERENCES muallif(id)

4.  kurs_teg(kurs_id, teg_id)  -- oraliq jadval

5.  email TEXT UNIQUE NOT NULL

Vazifa 3: Normalizatsiya

Takrorni yo'qot:

  1. Takrorli jadval
  2. Alohida jadvalga chiqar
  3. FK bilan bog'la
  4. JOIN bilan o'qi

Vazifa 4: Cheklovlar

Himoya:

  1. NOT NULL, UNIQUE
  2. CHECK (shart)
  3. FK
  4. Buzish urinishi (bloklanadi)

Vazifa 5: Bog'lanishlar

Uch tur:

  1. Bir-ko'p (FK)
  2. Ko'p-ko'p (oraliq)
  3. Bir-bir (FK)
  4. Har biri test

Vazifa 6: To'liq sxema

Loyiha:

  1. Entitylarni aniqla
  2. Jadval + kalit
  3. Bog'lanish + cheklov
  4. So'rov (JOIN)

Vazifa 7: O'ylash

Baza dizayni — 23-qismning yakuni — barcha o'rgangan bilimni (SQL, JOIN, indeks, ORM, NoSQL) birlashtiradi. Normalizatsiya "har fakt bir joyda" tamoyiliga asoslanadi — bu dasturlashning umumiy DRY (Don't Repeat Yourself — takrorlama) tamoyilining baza versiyasi. Nima uchun "har fakt bir manba" (single source of truth) muhim — baza dizaynida ham, kod'da ham, va yaxshi dizayn nima uchun oldindan o'ylashni (kod'dan keyin emas) talab qiladi?

Javob

Qisqa javob: Normalizatsiya — "har fakt bir joyda, bir marta" — bu DRY (Don't Repeat Yourself) tamoyilining baza versiyasi. Nima uchun muhim: takror bo'lsa, nomuvofiqlik xavfi (bir nusxa yangilandi, boshqasi eski qoldi — qaysi to'g'ri?). "Bitta haqiqat manbai" (single source of truth) — har fakt uchun bitta vakolatli joy. Bu kod'da ham (bir mantiq — bir funksiya, takror emas), bazada ham (bir fakt — bir jadval). Dizayn oldindan kerak, chunki bazani keyin o'zgartirish juda qiyin: ma'lumot ko'chirish (million satr), kod o'zgarish (barcha so'rov), ishlab turgan tizim (to'xtatib bo'lmaydi). Kod'ni refaktoring oson, sxemani — qiyin. "Dizaynga bir soat — keyin bir hafta tejaladi".

1. DRY va single source of truth

"Har fakt bir joyda" (normalizatsiya) = DRY (takrorlama). Har ma'lumot uchun bitta vakolatli manba. Takror → nomuvofiqlik (qaysi to'g'ri?).

2. Nega takror xavfli

Takror Muammo
Mijoz nomi 100 joyda O'zgarsa — 100 yangilash
Bittasi unutildi Nomuvofiqlik (qaysi to'g'ri?)
Joy isrofi Ko'p nusxa

3. Kod'da ham shu tamoyil

Baza Kod
Fakt bir jadvalda Mantiq bir funksiyada
Normalizatsiya DRY (takrorlama)
FK (havola) Import (havola)

4. Nega dizayn oldindan

O'zgartirish Qiyinlik
Kod refaktoring Oson (IDE, test)
Sxema o'zgartirish Qiyin (ma'lumot ko'chir, migratsiya)
Ishlab turgan baza Juda qiyin (to'xtatib bo'lmaydi)

Baza — poydevor (uy poydevori kabi): keyin o'zgartirish qimmat. Kod — devor (osonroq).

5. Muhandislik saboqlari

  1. Har fakt bir manba (DRY, normalizatsiya)
  2. Takror → nomuvofiqlik xavfi
  3. Dizayn oldindan (sxema o'zgarish qiyin)
  4. Baza — poydevor (ehtiyot bilan)

6. Xulosa

  1. Normalizatsiya = DRY (baza versiyasi)
  2. Single source of truth — nomuvofiqlikni oldini oladi
  3. Dizayn kod'dan oldin (o'zgarish qimmat)
  4. Yaxshi dizayn — vaqt tejaydi

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda — 23-qism yakuni — baza dizayni tamoyillarini o'rgandik.

Eng muhim uch fikr:

  1. Normalizatsiya — har fakt bir joyda. Normalizatsiya — ma'lumotni shunday tashkil qilishki, har fakt bir marta saqlansin (takror yo'q). Takror yomon: joy isrofi va nomuvofiqlik (bir joyda yangilandi, boshqasida yo'q). Yechim: takrorlanadigan ma'lumotni alohida jadvalga chiqar, havola (FK) bilan bog'la. Normal shakllar: 1NF (har katak bitta qiymat), 2NF (butun kalitga bog'liq), 3NF (faqat kalitga) — amaliyotda 3NF yetarli. Bu DRY (Don't Repeat Yourself) tamoyilining baza versiyasi — "bitta haqiqat manbai".

  2. Kalitlar, cheklovlar, bog'lanishlar. Birlamchi kalit (primary key — id) satrni noyob aniqlaydi; tashqi kalit (foreign key — muallif_id) boshqa jadvalga havola (bog'lanish). Cheklovlar baza to'g'riligini himoya qiladi: NOT NULL (bo'sh emas), UNIQUE (takrorsiz), CHECK (shart), FK (havola mavjud) — dastur xatosi ham bazani buzolmaydi. Bog'lanish turlari: bir-bir (FK), bir-ko'p (FK "ko'p" tomonda — eng keng tarqalgan), ko'p-ko'p (oraliq jadval — kurs_teg). Bu 23.1–23.3 (jadval, JOIN, indeks) ustida quriladi.

  3. Dizayn jarayoni va 23-qism yakuni. Dizayn: entity → jadval → bog'lanish → kalit → cheklov → normalizatsiya → indeks 23.3-bob. Denormalizatsiya — unumdorlik uchun ataylab takror (avval normalizatsiya, o'lchab kerak bo'lsa). Dizayn kod'dan oldin — sxemani keyin o'zgartirish juda qiyin (ma'lumot ko'chirish, migratsiya, ishlab turgan tizim). 23-qism yakuni: SQL asoslari (23.1–23.5), ORM (23.6–23.9 — SQLAlchemy Core/ORM, migratsiya, N+1), kesh (23.10 — Redis), NoSQL (23.11 — MongoDB), dizayn 23.12-bob. Ma'lumot — har ilovaning yuragi; uni to'g'ri saqlash, so'rash, loyihalash — muhim mahorat.

Keyingi qismda (24-qism: Ma'lumot tahlili) ma'lumot bilan ishlashni — NumPy (massiv, tez hisoblash), pandas (DataFrame, tozalash, guruhlash), Matplotlib/Seaborn (vizualizatsiya), statistikani o'rganamiz: ma'lumotdan xulosa chiqarish mahorati.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
23.12-dars: Baza dizayni tamoyillari — IlmHamroh