Index nima, qanday ishlaydi, qachon kerak
Muammodan boshlaylik
Saytingiz ishga tushdi, hammasi tez ishlardi. Bir yildan keyin buyurtmalar jadvalida 5 million qator. Mijoz "Mening buyurtmalarim" sahifasini ochadi:
SELECT * FROM buyurtmalar WHERE mijoz_id = 48213;
Sahifa 4 soniya yuklanadi. Kod o'zgarmagan. Server o'zgarmagan. Faqat ma'lumot ko'paydi.
Sabab: MySQL 48213-mijozning buyurtmalarini topish uchun 5 million qatorning har birini ko'rib chiqyapti. Bu — full table scan. Yechim — indeks.
Kitobdagi mundarija
1000 sahifalik kitobda "rekursiya" so'zi qayerda ekanini topish kerak.
Indekssiz: 1-sahifadan boshlab har bir sahifani o'qib chiqasiz. 1000 sahifa.
Indeks bilan: kitob oxiridagi alifbo ko'rsatkichini ochasiz. "R" harfi → "rekursiya — 412, 587-betlar". Alifbo tartibida bo'lgani uchun topish bir necha soniya. Keyin to'g'ridan-to'g'ri 412-betga o'tasiz.
MySQL indeksi — aynan shu ko'rsatkich: ustun qiymatlarining tartiblangan ro'yxati va har biri jadvaldagi qayerda turganiga ishora.
Indeks yaratish
CREATE INDEX idx_buyurtmalar_mijoz ON buyurtmalar (mijoz_id);
Yoki jadval yaratishda:
CREATE TABLE buyurtmalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
mijoz_id INT UNSIGNED NOT NULL,
holat VARCHAR(20) NOT NULL,
yaratilgan DATETIME NOT NULL,
INDEX idx_mijoz (mijoz_id),
INDEX idx_yaratilgan (yaratilgan)
);
Endi xuddi shu so'rov:
Indekssiz: 5 000 000 qator tekshirildi — 4.2 soniya
Indeks bilan: 12 qator tekshirildi — 0.001 soniya
Ming barobar tez. So'rovni o'zgartirish shart emas — MySQL indeksni o'zi topib ishlatadi.
Ichida nima bor: B-tree
MySQL (InnoDB) indekslari B+ tree tuzilmasida saqlanadi — muvozanatlashgan daraxt:
[ 500 | 1000 ] ← ildiz
/ | \
[100|250|400] [600|750|900] [1200|1500] ← oraliq tugunlar
/ | | \ ... ...
[1..99][100..249]... ← barglar: qiymat → qator manzili
mijoz_id = 750 ni qidirish:
- Ildiz: 750 — 500 va 1000 orasida → o'rta shoxga
- Oraliq: 750 topildi → bargga
- Barg: 750 → qatorlar manzili
3-4 qadam — 5 million qator bo'lsa ham. Har bir daraja yuzlab shoxchaga bo'linadi, shuning uchun daraxt juda "keng va past". Milliard qator — taxminan 4-5 daraja.
Barglar tartiblangan va bir-biriga bog'langan — shuning uchun indeks oraliq qidiruvlarni ham tezlashtiradi:
WHERE yaratilgan >= '2026-10-01' AND yaratilgan < '2026-11-01' -- ✅ indeks ishlaydi
ORDER BY yaratilgan -- ✅ tartiblash shart emas
Clustered index — PRIMARY KEY
InnoDB da jadvalning o'zi primary key bo'yicha tartiblangan B-tree. Bu clustered index: barglarda butun qator saqlanadi.
Boshqa indekslar (secondary index) barglarida esa qatorning o'zi emas, uning primary key qiymati:
idx_mijoz: mijoz_id=48213 → id=[1043, 2981, 5502]
↓
PRIMARY: id=1043 → [butun qator]
Shuning uchun:
WHERE id = 5— eng tez qidiruv (bitta daraxt)WHERE mijoz_id = 48213— ikki qadam: secondary indeks → primary key → qator- Primary key qisqa bo'lsin (
INT,BIGINT) — u har bir secondary indeksda takrorlanadi
Indeksning narxi
Indeks bepul emas:
| Ta'siri | |
|---|---|
SELECT |
✅ Tezlashadi |
INSERT |
❌ Sekinlashadi — har bir indeksga yozish kerak |
UPDATE (indekslangan ustun) |
❌ Sekinlashadi |
DELETE |
❌ Sekinlashadi |
| Disk | ❌ Qo'shimcha joy (ba'zan jadvalning o'zidan katta) |
| Xotira (buffer pool) | ❌ Indeks sahifalari ham keshda joy egallaydi |
10 ta indeksli jadvalga har bir INSERT — 11 ta B-tree ga yozish.
Qoida: har bir ustunga indeks qo'ymang. Haqiqatan qidiriladigan ustunlarga qo'ying.
Qachon indeks kerak
✅ Kerak:
WHEREda tez-tez ishlatiladigan ustunlar:email,holat,yaratilganJOIN ... ONdagi ustunlar — foreign key lar (MySQL avtomatik yaratadi)ORDER BYdagi ustunlar (ayniqsaLIMITbilan)UNIQUEbo'lishi kerak bo'lgan ustunlar
❌ Kerak emas yoki foydasiz:
- Kichik jadvallar (bir necha yuz qator) — to'liq ko'rib chiqish baribir tez
- Kam qiymatli ustunlar (past selectivity) —
jinsi(2 qiymat),faol(true/false). Qatorlarning yarmini indeks orqali o'qish to'liq ko'rib chiqishdan sekinroq - Faqat yoziladigan, deyarli o'qilmaydigan jadvallar (loglar)
- Hech qachon
WHEREda ishlatilmaydigan ustunlar
Selectivity
SELECT
COUNT(DISTINCT email) / COUNT(*) AS email_selectivity, -- ~1.0 — a'lo
COUNT(DISTINCT shahar) / COUNT(*) AS shahar_selectivity, -- ~0.001 — yomon
COUNT(DISTINCT holat) / COUNT(*) AS holat_selectivity -- ~0.000001
FROM mijozlar;
1 ga qanchalik yaqin bo'lsa — indeks shunchalik foydali.
Indeks ishlamay qoladigan holatlar
Indeks bor, lekin MySQL undan foydalana olmaydi:
-- 1. Ustun funksiyaga o'ralgan
WHERE YEAR(yaratilgan) = 2026 -- ❌
WHERE yaratilgan >= '2026-01-01' AND yaratilgan < '2027-01-01' -- ✅
-- 2. Ustun ustida hisob
WHERE narx * 1.12 > 1000000 -- ❌
WHERE narx > 1000000 / 1.12 -- ✅
-- 3. Boshida % bilan LIKE
WHERE nom LIKE '%phone' -- ❌
WHERE nom LIKE 'iPhone%' -- ✅
-- 4. Tur mos emas — matn ustunni son bilan solishtirish
WHERE telefon = 998901112233 -- ❌ (har bir qator songa aylantiriladi)
WHERE telefon = '998901112233' -- ✅
Umumiy qoida: indekslangan ustun WHERE da "yalang'och" tursin.
Indekslarni ko'rish va o'chirish
SHOW INDEX FROM buyurtmalar;
DROP INDEX idx_buyurtmalar_mijoz ON buyurtmalar;
MySQL so'rovda indeksdan foydalanyaptimi — EXPLAIN bilan tekshiriladi (32-dars):
EXPLAIN SELECT * FROM buyurtmalar WHERE mijoz_id = 48213;
-- key: idx_buyurtmalar_mijoz, rows: 12 ✅
-- key: NULL, rows: 5000000, type: ALL ❌ full table scan
Nima uchun shunday?
Nima uchun MySQL barcha ustunlarga avtomatik indeks qo'ymaydi, agar u bunchalik foydali bo'lsa?
Chunki indeksning foydasi so'rovlarga bog'liq, MySQL esa siz qanday so'rov yozishingizni oldindan bilmaydi. Har bir ustunga indeks — har bir yozishni o'nlab marta sekinlashtirish va diskni bir necha barobar to'ldirish. Indeks — almashuv: o'qish tezligi evaziga yozish tezligi va joy. Bu almashuvni faqat ilovani biladigan odam — siz — to'g'ri qila olasiz.
Xulosa
Eslab qoling:
- Indeks — ustun qiymatlarining tartiblangan ko'rsatkichi (B+ tree)
- Millionlab qatorda ham 3-4 qadamda topadi; oraliq va
ORDER BYni ham tezlashtiradi - PRIMARY KEY — clustered index: jadvalning o'zi shu tartibda
- Secondary index → primary key → qator
- Narxi: sekinroq
INSERT/UPDATE/DELETE, qo'shimcha disk va xotira WHERE,JOIN,ORDER BYdagi, selectivity yuqori ustunlarga qo'ying- Ustunni funksiyaga o'rasangiz yoki
LIKE '%...'— indeks ishlamaydi
Keyingi dars
31-dars: Index turlari — PRIMARY, UNIQUE, COMPOSITE, FULLTEXT