3-bo‘lim

Kalitlar

Birlamchi, nomzod va kompozit kalitlar, tabiiy va sun'iy kalit tanlovi, AUTO_INCREMENT va UUID.

🕑 15 daqiqa o‘qish 📄 1 023 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Kalit turlari
  2. Nomzod kalitlarni topish
  3. Tabiiy va sun'iy kalit
  4. AUTO_INCREMENT xatti-harakati
  5. Kompozit kalit
  6. UUID - taqsimlangan tizimlar uchun
  7. Kalit tanlash qoidalari
  8. Xulosa

Kalit - qatorni bir ma'noli aniqlaydigan ustun yoki ustunlar to'plami. Uni to'g'ri tanlash - loyihalashning eng muhim qarorlaridan.

Kalit turlari #

Kalitlar ierarxiyasi Super kalit Qatorni aniqlaydigan ISTALGAN ustunlar to'plami Nomzod kalit Ortiqcha ustunsiz eng kichik super kalit Birlamchi kalit Siz tanlagan bitta nomzod kalit Qolgan nomzod kalitlar UNIQUE bo'lib qoladi Jadvalda birlamchi kalit BITTA, nomzod kalit bir nechta bo'ladi
Har bir birlamchi kalit - nomzod kalit, lekin teskarisi shart emas

Nomzod kalitlarni topish #

SQL
CREATE TABLE xodimlar (
    id             INT PRIMARY KEY AUTO_INCREMENT,
    pasport        CHAR(9)      NOT NULL UNIQUE,
    email          VARCHAR(100) NOT NULL UNIQUE,
    ism            VARCHAR(100) NOT NULL,
    familiya       VARCHAR(100) NOT NULL,
    bolim          VARCHAR(50)  NOT NULL,
    ish_boshlagan  DATE         NOT NULL
);

INSERT INTO xodimlar (pasport, email, ism, familiya, bolim, ish_boshlagan) VALUES
    ('AA1234567', '[email protected]', 'Husanboy', 'Qodirov',  'IT',      '2024-01-15'),
    ('AB7654321', '[email protected]',   'Malika',   'Yusupova', 'Hisobot', '2024-03-01'),
    ('AC1112223', '[email protected]',   'Nodira',   'Karimova', 'IT',      '2025-06-10');
SQL
-- Uchta nomzod kalit bor: id, pasport, email
SELECT CONSTRAINT_NAME AS cheklov, COLUMN_NAME AS ustun
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xodimlar'
ORDER BY BINARY CONSTRAINT_NAME;
Natija
+---------+---------+
| cheklov | ustun   |
+---------+---------+
| PRIMARY | id      |
| email   | email   |
| pasport | pasport |
+---------+---------+
Nomzod kalitni qanday aniqlash

Ustun (yoki ustunlar to'plami) nomzod kalit bo'lishi uchun ikki shart kerak:

  1. Yagonalik - hech ikki qatorda takrorlanmaydi;
  2. Qisqarmaslik - undan istalgan ustunni olib tashlasangiz, yagonalik yo'qoladi.

Misol: (ism, familiya) yagona bo'lishi mumkin, lekin bu biznes kafolati emas - ikkita "Husanboy Qodirov" bo'lishi mumkin.

Nomzod kalit haqiqiy dunyodagi qoidaga tayanishi kerak, sizning ma'lumotingizdagi tasodifga emas:

UstunNomzod kalitmiNima uchun
pasportHaDavlat kafolatlaydi
emailHaTizim kafolatlaydi
(ism, familiya)Yo'qTakrorlanishi mumkin
telefonEhtimolOilaviy raqam bo'lishi mumkin

"Hozircha takrorlanmayapti" - kalit tanlash uchun yetarli asos emas.

Tabiiy va sun'iy kalit #

SQL
-- Tabiiy kalit: haqiqiy dunyodan keladi (pasport)
SELECT pasport, ism FROM xodimlar WHERE pasport = 'AA1234567';
Natija
+-----------+----------+
| pasport   | ism      |
+-----------+----------+
| AA1234567 | Husanboy |
+-----------+----------+
SQL
-- Sun'iy kalit: tizim o'zi yaratadi, ma'nosi yo'q
SELECT id, ism FROM xodimlar ORDER BY id;
Natija
+----+----------+
| id | ism      |
+----+----------+
|  1 | Husanboy |
|  2 | Malika   |
|  3 | Nodira   |
+----+----------+
Qaysi kalitni tanlash kerak? Tabiiy kalit pasport, ISBN, INN + Ma'noga ega + Qo'shimcha ustun kerak emas - O'zgarishi mumkin - Uzun bo'lishi mumkin - Maxfiy ma'lumot bo'lishi mumkin - Boshida bo'lmasligi mumkin Sun'iy kalit AUTO_INCREMENT, UUID + Hech qachon o'zgarmaydi + Qisqa va tez + Doim mavjud + Maxfiy ma'lumot emas - Qo'shimcha ustun Amalda ko'pincha shu tanlanadi
Tabiiy kalitni UNIQUE sifatida saqlab, birlamchi kalitga sun'iysini oling
Tabiiy kalit o'zgarganda nima bo'ladi

Aytaylik pasport ni birlamchi kalit qilib oldingiz. Undan o'nlab jadval FOREIGN KEY orqali foydalanadi.

Endi xodim pasportini almashtirdi (muddati tugadi, familiya o'zgardi). Nima qilish kerak?

  • Barcha bog'liq jadvallardagi qiymatni yangilash;
  • ON UPDATE CASCADE yordam beradi, lekin million qatorda bu soatlab ishlaydi va jadvallarni qulflaydi;
  • Tarixiy hisobotlar eski qiymatga ishora qilib qolgan bo'lishi mumkin.

Sun'iy kalitda esa bu muammo umuman yo'q - id hech qachon o'zgarmaydi, pasport esa oddiy ustun bo'lib qoladi:

SQL
UPDATE xodimlar SET pasport = 'AD9998887' WHERE id = 1;

Bitta qator, hech qanday zanjirli ta'sir.

Amaliy tavsiya: birlamchi kalit uchun sun'iy kalit oling, tabiiy kalitni esa UNIQUE cheklov sifatida saqlang. Shunda ikkala foydani ham olasiz.

AUTO_INCREMENT xatti-harakati #

SQL
INSERT INTO xodimlar (pasport, email, ism, familiya, bolim, ish_boshlagan)
VALUES ('AD5556667', '[email protected]', 'Aziza', 'Tosheva', 'IT', '2026-01-05');

SELECT LAST_INSERT_ID() AS oxirgi_id;
Natija
+-----------+
| oxirgi_id |
+-----------+
|         4 |
+-----------+
SQL
-- To'rtinchi xodimni qo'shamiz, keyin o'chiramiz
INSERT INTO xodimlar (pasport, email, ism, familiya, bolim, ish_boshlagan)
VALUES ('AD5556667', '[email protected]', 'Aziza', 'Tosheva', 'IT', '2026-01-05');

DELETE FROM xodimlar WHERE id = 4;

-- Yangi qator 4 ni EMAS, 5 ni oladi
INSERT INTO xodimlar (pasport, email, ism, familiya, bolim, ish_boshlagan)
VALUES ('AE1112223', '[email protected]', 'Kamola', 'Rasulova', 'Hisobot', '2026-02-01');

SELECT id, ism FROM xodimlar ORDER BY id;
Natija
+----+----------+
| id | ism      |
+----+----------+
|  1 | Husanboy |
|  2 | Malika   |
|  3 | Nodira   |
|  5 | Kamola   |
+----+----------+
id da bo'shliq bo'lishi normal

4 raqami yo'qolib qoldi va bu muammo emas.

AUTO_INCREMENT qiymatlari ketma-ket bo'lishini kafolatlamaydi. Bo'shliq quyidagi hollarda paydo bo'ladi:

SababIzoh
Qator o'chirildiRaqam qaytarilmaydi
Tranzaksiya bekor qilindiRaqam allaqachon "band"
INSERT xato berdiRaqam sarflandi
Server qayta yuklandiBa'zi versiyalarda sakrash

Hech qachon id ni "qatorlar soni" yoki "tartib raqami" sifatida ishlatmang:

SQL
-- NOTO'G'RI - bo'shliq bo'lsa xato natija
SELECT MAX(id) AS xodimlar_soni FROM xodimlar;

-- TO'G'RI
SELECT COUNT(*) AS xodimlar_soni FROM xodimlar;

Foydalanuvchiga ko'rsatiladigan tartib raqami kerak bo'lsa, uni alohida ustunda saqlang yoki ROW_NUMBER() bilan hisoblang.

Kompozit kalit #

SQL
CREATE TABLE dars_jadvali (
    sinf_id     INT NOT NULL,
    kun         TINYINT NOT NULL,
    juftlik     TINYINT NOT NULL,
    fan         VARCHAR(50) NOT NULL,
    PRIMARY KEY (sinf_id, kun, juftlik)
);

INSERT INTO dars_jadvali VALUES
    (1, 1, 1, 'Matematika'),
    (1, 1, 2, 'Fizika'),
    (2, 1, 1, 'Ingliz tili');

SELECT sinf_id, kun, juftlik, fan FROM dars_jadvali ORDER BY sinf_id, kun, juftlik;
Natija
+---------+-----+---------+-------------+
| sinf_id | kun | juftlik | fan         |
+---------+-----+---------+-------------+
|       1 |   1 |       1 | Matematika  |
|       1 |   1 |       2 | Fizika      |
|       2 |   1 |       1 | Ingliz tili |
+---------+-----+---------+-------------+
SQL
-- Bir sinfda bir vaqtda ikki dars bo'la olmaydi
INSERT INTO dars_jadvali VALUES (1, 1, 1, 'Tarix');
Natija
ERROR 1062 (23000): Duplicate entry '1-1-1' for key 'PRIMARY'
Kompozit kalit qachon to'g'ri

Kompozit birlamchi kalit bog'lovchi jadvallarda va tabiiy ravishda ko'p ustunli ma'lumotda o'rinli:

SQL
PRIMARY KEY (buyurtma_id, mahsulot_id)     -- bog'lovchi jadval
PRIMARY KEY (sinf_id, kun, juftlik)        -- jadval kataklari

Afzalligi - biznes qoidasi sxemada mustahkamlangan. "Bir sinfda bir vaqtda bitta dars" qoidasini kod buzolmaydi.

Kamchiliklari:

MuammoIzoh
Uchinchi jadvaldan murojaatUchala ustunni ko'chirish kerak
Indeks kattaligiKo'proq joy egallaydi
ORM lar bilan ishlashBa'zilari qo'llab-quvvatlamaydi
So'rovlar uzunroqON a.x=b.x AND a.y=b.y AND ...

Agar shu jadvalga boshqa jadval murojaat qiladigan bo'lsa, sun'iy id qo'shib, kompozitni UNIQUE ga aylantiring:

SQL
id INT PRIMARY KEY AUTO_INCREMENT,
UNIQUE (sinf_id, kun, juftlik)

Bu ikkala foydani beradi: qisqa murojaat va mustahkamlangan qoida.

UUID - taqsimlangan tizimlar uchun #

SQL
CREATE TABLE hujjatlar (
    id       BINARY(16) PRIMARY KEY,
    sarlavha VARCHAR(200) NOT NULL
);

-- UNHEX bilan 36 belgilik matnni 16 baytga siqamiz
INSERT INTO hujjatlar VALUES
    (UNHEX(REPLACE('11111111-2222-3333-4444-555555555555', '-', '')), 'Shartnoma'),
    (UNHEX(REPLACE('66666666-7777-8888-9999-000000000000', '-', '')), 'Hisobot');

SELECT LOWER(HEX(id)) AS saqlangan, sarlavha, LENGTH(id) AS bayt
FROM hujjatlar
ORDER BY sarlavha;
Natija
+----------------------------------+-----------+------+
| saqlangan                        | sarlavha  | bayt |
+----------------------------------+-----------+------+
| 66666666777788889999000000000000 | Hisobot   |   16 |
| 11111111222233334444555555555555 | Shartnoma |   16 |
+----------------------------------+-----------+------+
UUID ni CHAR(36) da saqlamang

UUID ni matn sifatida saqlash keng tarqalgan, lekin qimmat xato:

Saqlash usuliHajmiIzoh
CHAR(36)36 baytO'qish oson, lekin isrof
BINARY(16)16 baytIkki barobardan ko'p tejash

Birlamchi kalit har bir ikkilamchi indeksga ham kiritiladi, shuning uchun farq ko'payadi. Million qatorli, 5 ta indeksli jadvalda bu 100 MB dan ortiq farq beradi.

Ikkinchi muammo tasodifiylik: klassik UUID v4 butunlay tasodifiy. InnoDB esa qatorlarni birlamchi kalit tartibida saqlaydi - tasodifiy kalit har INSERT da indeksni o'rtasidan buzadi (page split).

Yechim - vaqt bo'yicha tartiblangan UUID:

  • UUID v7 - zamonaviy standart, vaqt prefiksli;
  • MySQL 8 va MariaDB 10.10+ da UUID_TO_BIN(uuid, 1) - bo'laklarni almashtirib, vaqt qismini boshiga chiqaradi.

Eski versiyalarda yuqoridagi UNHEX(REPLACE(...)) usuli ishlaydi - u hamma joyda mavjud.

Ehtiyoj bo'lmasa esa oddiy AUTO_INCREMENT eng tez va eng ixchamdir. UUID faqat quyidagi hollarda kerak:

  • Bir necha server mustaqil id yaratsa;
  • id ni URL da ko'rsatib, sonini yashirish kerak bo'lsa;
  • Ma'lumot bazalar orasida birlashtirilsa.

Kalit tanlash qoidalari #

Amaliy tavsiyalar
QoidaSabab
Har jadvalda birlamchi kalit bo'lsinQatorni aniqlash, replikatsiya
Sun'iy kalitni birlamchi qilingO'zgarmaydi
Tabiiy kalitni UNIQUE qilingQoida saqlanadi
Kalit qisqa bo'lsinIndekslarga ko'chiriladi
Kalitni o'zgartirmangZanjirli yangilanish qimmat
Maxfiy ma'lumotni kalit qilmangPasport URL da ko'rinmasin
id ni tartib raqami deb bilmangBo'shliqlar bor

Birlamchi kalitsiz jadval InnoDB da baribir yashirin kalit oladi, lekin siz undan foydalana olmaysiz - va replikatsiya sekinlashadi.

Amaliy topshiriq
  1. Jadvaldagi barcha nomzod kalitlarni toping.
  2. (ism, familiya) nima uchun kalit bo'la olmasligini ayting.
  3. Tabiiy va sun'iy kalitning uchtadan afzalligini sanang.
  4. Tabiiy kalit o'zgarganda nima bo'lishini tushuntiring.
  5. Qator o'chirib, id da bo'shliq hosil qiling.
  6. MAX(id) va COUNT(*) farqini ko'rsating.
  7. Uch ustunli kompozit kalit yarating.
  8. Kompozit kalitni buzuvchi INSERT yozing.
  9. UUID ni BINARY(16) da saqlang.
  10. UUID v4 ning InnoDB dagi muammosini tushuntiring.

Xulosa #

  • Super kalitnomzod kalitbirlamchi kalit.
  • Nomzod kalit yagona va qisqarmas bo'lishi kerak.
  • "Hozircha takrorlanmayapti" - kalit uchun asos emas.
  • Sun'iy kalitni birlamchi, tabiiyni UNIQUE qiling.
  • Tabiiy kalit o'zgarsa zanjirli yangilanish kerak bo'ladi.
  • AUTO_INCREMENT da bo'shliq normal - id tartib raqami emas.
  • Qatorlar sonini COUNT(*) bilan oling, MAX(id) bilan emas.
  • Kompozit kalit bog'lovchi jadvallarda o'rinli.
  • Boshqa jadval murojaat qilsa - sun'iy id qo'shing.
  • UUID ni BINARY(16) da saqlang, CHAR(36) da emas.
  • Tasodifiy UUID InnoDB indeksini buzadi - v7 ishlating.

Keyingi bo'limda bir-ga-ko'p bog'lanishni batafsil ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.