6.10-bob: Indekslar va query optimization, EXPLAIN
6-QISM — Ma'lumotlar bazasi (Database) · 10-mavzu
1. Kirish va motivatsiya
Toza DB dizayni (normalizatsiya) va yaxlitlik (ACID — 6.9)ni bildik. Endi DB'ning eng amaliy, production'da eng muhim mavzusiga — tezlikka — o'tamiz: indekslar (chuqur), query optimization (so'rovni tezlashtirish), va EXPLAIN (so'rov rejasini ko'rish). Bu mavzu — ilovangiz sekin yoki tez ishlashini belgilaydi; va sekin DB — eng ko'p uchraydigan production muammosi.
Tasavvur qiling: loyihangiz yangi — 100 ta foydalanuvchi, hammasi tez. Bir yildan keyin — 1 million foydalanuvchi, va to'satdan ilova sekinlashdi (sahifa 10 sekund yuklanadi). Sabab — deyarli har doim indekssiz so'rovlar: DB har so'rovda butun jadvalni (millionlab qator) birma-bir ko'rib chiqadi. Yechim — indeks: kerakli ma'lumotni darrov topish (kitobning mundarijasi kabi). Indeks bilan — 1 million qatorda ham bir necha millisekund.
6.3 (MongoDB) va 6.6 (PostgreSQL) da indekslarni qisman ko'rdik. Endi chuqur: B-tree qanday ishlaydi, composite/covering/partial indekslar, EXPLAIN ANALYZE (so'rov rejasini o'qish — sekin so'rovni aniqlash), va optimizatsiya amaliyotlari. Bu — backend dasturchini "ishlaydigan kod yozadi"dan "tez, masshtablanadigan tizim quradi"ga ko'taradi (intervyularda ham eng qadrlanadigan bilim).
O'xshatish (indeks): kitobda biror so'zni topish — ikki yo'l. Indekssiz: birinchi sahifadan oxirigacha har sahifani o'qish (1000 sahifa — uzoq). Indeks bilan: kitob oxiridagi alfavit ko'rsatkichka qarash "bu so'z 347-sahifada" to'g'ridan o'sha sahifa (bir necha qadam). DB indeksi — aynan shu alfavit ko'rsatkich: ma'lumotni saralangan holda saqlab, darrov topish imkonini beradi.
Nega muhim?
- Tezlik = hayot — indekssiz katta DB sekin (eng ko'p production muammosi).
- Masshtab — million qatorda ham tez ishlash indeksga bog'liq.
- EXPLAIN — sekin so'rovni topish va tuzatishning yagona yo'li.
- Ekspertlik — indeks/optimizatsiya — senior backend belgisi.
2. Nazariya — chuqur tushuntirish
2.1. Indekssiz qidiruv muammosi (full scan)
Indekssiz, DB qidiruvni butun jadvalni ko'rib chiqib bajaradi (full table scan / sequential scan):
SELECT * FROM users WHERE email = 'ali@a.uz';
Indekssiz (Seq Scan):
1-qator: email = 'ali@a.uz'? yo'q
2-qator: ? yo'q
... (1,000,000 qator birma-bir) ...
O(n) — qatorlar soniga proporsional (sekin — 3.1: Big-O)
1 million qatorda — har so'rov millionlab tekshiruv (sekin!)Bu — kichik jadvalda muammo emas (100 qator — tez). Lekin katta jadvalda (million+) — falokat. Va jadval o'sgan sari sekinlashadi. Indeks — bu muammoni hal qiladi.
2.2. Indeks nima va B-tree (chuqur)
Indeks — ustun(lar) bo'yicha saralangan, alohida tuzilma (asosiy jadvaldan tashqari). Standart turi — B-tree (balanslangan daraxt — 3.6, freecodecamp):
B-tree (balanced tree — 3.6):
[M]
/ \
[F] [T]
/ \ / \
[A-E] [G-L] [N-S] [U-Z]
"ali@a.uz" qidirish: M'dan kichik F A-E barglari topildi
O(log n) — har qadamda yarmini tashlaydi (3.1: Big-O)
1,000,000 qator: log₂(1M) ≈ 20 qadam (millionlab emas!)B-tree kuchi: qidiruvni
O(n)(full scan) danO(log n)(daraxt) ga keltiradi. 1 million qator: 1,000,000 tekshiruv o'rniga ~20 qadam. Bu — ming barobar tez. B-tree saralangan — tartiblash (ORDER BY), oraliq (BETWEEN) ham tez.
2.3. Indeks qanday yaratiladi
-- Yagona ustun
CREATE INDEX idx_users_email ON users (email);
-- Noyob (unique — ham indeks, ham cheklov — 6.4: 2.5)
CREATE UNIQUE INDEX idx_users_email ON users (email);
-- Composite (ko'p ustun — 2.5)
CREATE INDEX idx_orders_user_date ON orders (user_id, created_at);
-- Indeksni o'chirish
DROP INDEX idx_users_email;Primary Key avtomatik indekslangan 6.4-bob. Unique constraint ham indeks yaratadi. Foreign Key — avtomatik indekslanmaydi (ko'p DB'da) — JOIN tezligi uchun qo'lda qo'shish kerak 2.10-bob.
2.4. Qaysi ustunga indeks (va qaysiga emas)
Indeks kerak:
- WHERE'da tez-tez ishlatiladigan (email, status, user_id)
- JOIN ustunlari (FK — 2.10)
- ORDER BY ustunlari
- UNIQUE bo'lishi kerak (email)
Indeks kerak emas / zarari:
- Kichik jadval (full scan baribir tez)
- Kam ishlatiladigan ustun
- Tez-tez o'zgaradigan, kam qidiriladigan (yozish sekinlashadi)
- Past kardinallik (faqat 2-3 qiymat — masalan boolean — kam foyda)Kardinallik — ustundagi noyob qiymatlar soni. Yuqori (email — har xil) indeks foydali. Past (jins: erkak/ayol — 2 qiymat) indeks kam foyda (yarmini baribir o'qiydi). Indeks — yuqori kardinallikli, tez-qidiriladigan ustunga.
2.5. Composite (birikma) indeks va ustun tartibi
Composite indeks — bir necha ustun bo'yicha. Ustun tartibi — eng muhim qaror (ai2sql):
CREATE INDEX idx ON orders (user_id, created_at, status); (a, b, c) indeksi QO'LLAB-QUVVATLAYDI:
WHERE a (faqat birinchi)
WHERE a AND b (chapdan ketma-ket)
WHERE a AND b AND c
WHERE b (birinchini o'tkazib — ishlamaydi!)
WHERE c
WHERE b AND c
"leftmost prefix" qoidasi: chapdan boshlab ketma-ket ustunlarComposite indeks — chapdan (leftmost prefix):
(a, b, c)indeksia,a+b,a+b+cso'rovlariga ishlaydi, lekinbyokicyolg'iz uchun ishlamaydi. Shuning uchun tartib muhim: eng ko'p filtrlanadiganni birinchi. ESR qoidasi (6.3: 2.9): Equality Sort Range.
2.6. Covering index (qoplovchi indeks)
Covering index — so'rov kerakli barcha ustunlarni o'z ichiga oladi DB jadvalga umuman murojaat qilmaydi (faqat indeksdan — ai2sql):
-- So'rov: SELECT ism, email FROM users WHERE status = 'faol';
CREATE INDEX idx_cover ON users (status) INCLUDE (ism, email); -- PostgreSQL 11+
-- status bo'yicha topadi + ism/email indeksda jadval O'QILMAYDI (juda tez)Covering index — eng tez: DB indeksdan hamma narsani oladi (jadvalga "key lookup" — qimmat qadam — kerak emas).
INCLUDE(PostgreSQL) — qo'shimcha ustunlarni indeksda saqlaydi (qidiruvga emas, qaytarishga). Tez-tez ishlatiladigan, muhim so'rovlar uchun.
2.7. Partial index (qisman indeks)
Partial index — faqat ma'lum qatorlarga indeks (shart bilan):
-- Faqat faol foydalanuvchilar (o'chirilmaganlar) indekslanadi
CREATE INDEX idx_faol ON users (email) WHERE deleted_at IS NULL;
-- Faqat tugallanmagan buyurtmalar (tez-qidiriladigan kichik qism)
CREATE INDEX idx_kutilmoqda ON orders (created_at) WHERE status = 'kutilmoqda';Partial index — kichikroq (faqat kerakli qatorlar), tezroq, kam joy. Misol: 1 million buyurtmaning faqat 1000 tasi "kutilmoqda" — faqat shularga indeks (admin panel uchun). PostgreSQL'da kuchli (MySQL'da yo'q).
2.8. Boshqa indeks turlari (qisqacha)
B-tree — default (tenglik, oraliq, tartib — 2.2)
Hash — faqat tenglik (=) — kamdan-kam (B-tree odatda yetadi)
GIN — JSONB, massiv, to'liq matn (6.6: 2.11)
GiST — geometrik, range
BRIN — juda katta, tartiblangan (vaqt seriyasi — kam joy)Ko'p holatda B-tree (default). GIN — JSONB/massiv/matn 6.6-bob. Boshqalar — maxsus holatlar. Indeks turini ma'lumot va so'rovga qarab tanlang.
2.9. EXPLAIN — so'rov rejasini ko'rish (eng muhim vosita)
EXPLAIN — DB so'rovni qanday bajarishini ko'rsatadi (reja — oneuptime):
EXPLAIN SELECT * FROM users WHERE email = 'ali@a.uz';
-- Reja: Seq Scan (yomon — full scan!) yoki Index Scan (yaxshi)
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'ali@a.uz';
-- ANALYZE — so'rovni HAQIQATAN bajaradi + ASL vaqtni ko'rsatadi Reja turlari (PostgreSQL):
Seq Scan — butun jadval (indekssiz — YOMON katta jadvalda — 2.1)
Index Scan — indeksdan topish (YAXSHI — 2.2)
Index Only Scan — faqat indeksdan (covering — eng tez — 2.6)
Bitmap Scan — ko'p qator (oraliq)
Nested Loop / Hash Join — JOIN usullariEXPLAIN ANALYZE — optimizatsiyaning kaliti (oneuptime): indeks qo'shishdan oldin va keyin EXPLAIN ANALYZE bilan tekshiring.
Seq Scankatta jadvalda — yomon belgi (indeks kerak).Index Scan— yaxshi. "Reja"ni o'qish — sekin so'rovni topish va tuzatishning yagona ishonchli yo'li.
2.10. EXPLAIN'ni o'qish (nimaga e'tibor)
EXPLAIN ANALYZE natijasida:
- Seq Scan vs Index Scan (indeks ishlatilyaptimi)
- "Filter" — indeksdan keyin qo'shimcha filtr (ko'p qator o'qildi — yomon)
- "Index Cond" — indeks shartlari (yaxshi — filtr indeksda)
- actual time — haqiqiy vaqt (ms)
- rows — qancha qator qaytdi/o'qildi
- cost — DB baholagan "narx"Asosiy qoida (ai2sql): "Filter" ko'rsangiz — kerakidan ko'p qator o'qilmoqda (indeks yetmaydi). Ideal: filtrlash "Index Cond" ichida (indeksda).
actual timekatta yokirowskutilganidan ko'p — muammo belgisi.
2.11. N+1 muammosi (eng ko'p uchraydigan)
N+1 query — eng keng tarqalgan performance muammosi (6.7: 1-holat, ORM'da ham — 6.14):
N+1 (1 + N so'rov):
const users = await q("SELECT * FROM users"); // 1 so'rov
for (const u of users) // N foydalanuvchi
u.orders = await q("SELECT * FROM orders WHERE user_id = $1", [u.id]); // N so'rov!
1 + 100 = 101 so'rov (sekin!)
Bitta JOIN yoki IN:
await q("SELECT u.*, o.* FROM users u LEFT JOIN orders o ON u.id = o.user_id"); // 1 so'rov
yoki: WHERE user_id IN (...) // 2 so'rovN+1 — ayniqsa ORM'da (6.14 — populate/include) yashirin. 100 element 101 so'rov sekin. Yechim: JOIN 6.7-bob,
IN, yoki ORM'ning eager loading (include/populate). EXPLAIN bilan ko'rinmaydi (ko'p alohida so'rov) — kodni tekshirish kerak.
2.12. Query optimization amaliyotlari
Kerakli ustunlarni tanlang (SELECT * emas — kam ma'lumot, covering imkoni — 6.4)
WHERE'ni indekslangan ustunga (Seq Scan'dan saqlanish — 2.9)
Funksiyani indekslangan ustunga qo'llamang (WHERE LOWER(email) — indeks ishlamaydi!)
LIMIT bilan cheklash (katta natija — 6.4)
JOIN o'rniga subquery yoki teskari (o'lchab)
Sahifalashda OFFSET o'rniga keyset (katta sahifa — 2.13)
EXPLAIN ANALYZE bilan o'lchang (taxmin qilmang — 2.9)Funksiya indeksni buzadi:
WHERE LOWER(email) = 'ali@a.uz'—CREATE INDEX ON users (LOWER(email))) yoki ma'lumotni normallashtirib saqlash (kichik harf). Bu — yashirin sekinlik sababi.
2.13. Keyset pagination (katta sahifalash)
-- OFFSET — katta sahifada sekin (DB barcha oldingilarni o'qiydi)
SELECT * FROM posts ORDER BY id DESC LIMIT 20 OFFSET 100000; -- 100020 qator o'qiydi!
-- Keyset (cursor) — oxirgi ko'rilgandan keyin (tez)
SELECT * FROM posts WHERE id < $1 ORDER BY id DESC LIMIT 20; -- $1 = oxirgi idOFFSET muammosi:
OFFSET 100000— DB 100000 qatorni o'qib tashlaydi (sekin). Keyset pagination — "oxirgi ko'rilgan id'dan keyin" (indeks bilan to'g'ridan) — katta sahifada ham tez. Cheksiz scroll (feed) uchun ideal.
2.14. Indeks narxi (yana — balans)
Har indeks:
O'qishni tezlashtiradi (qidiruv — 2.2)
Yozishni sekinlashtiradi (INSERT/UPDATE/DELETE'da indeks ham yangilanadi)
Joy oladi (disk/RAM)
Kerakli indekslar (tez-qidiriladigan); ortiqcha emas
Yozish ko'p jadvalda — ehtiyot (har indeks yozishni sekinlatadi)Balans: indeks — o'qish uchun yaxshi, yozish uchun yuk. O'qish ko'p (mahsulot katalogi) ko'proq indeks. Yozish ko'p (log) kam indeks. Ishlatilmaydigan indekslarni o'chiring (joy + yozish tejaydi —
pg_stat_user_indexesbilan topish).
2.15. Boshqa optimizatsiya (qisqacha)
Connection pool (6.5, 6.6) — ulanish qayta ishlatish
Kesh (Redis — 5.21) — tez-o'qiladigan natija
Materialized view 6.8-bob — og'ir hisobot keshlash
Denormalizatsiya (6.9: 2.7) — JOIN kamaytirish
VACUUM/ANALYZE (PostgreSQL) — statistikani yangilash (optimizator uchun)
Read replica — o'qishni alohida serverga (masshtab — 9)2.16. Best practices (14)
WHERE/JOIN/ORDER BY ustunlariga indeks (2.4, 2.10)
Composite indeks — to'g'ri tartib (leftmost, ESR — 2.5)
EXPLAIN ANALYZE bilan o'lchang (taxmin qilmang — 2.9)
Seq Scan (katta jadval) — indeks qo'shing; Filter Index Cond 2.10-bob
N+1 dan saqlaning (JOIN/IN/eager — 2.11)
Funksiya indeksni buzadi (functional index — 2.12)
Katta sahifalash — keyset (OFFSET emas — 2.13)
Ortiqcha indeks emas (yozish narxi — 2.14)
SELECT kerakli ustunlar; kesh 5.21-bob tez-o'qiladiganga3. Sintaksis — tez ma'lumotnoma
-- Indeks (2.3, 2.5-2.7)
CREATE INDEX idx ON jadval (ustun); -- B-tree
CREATE INDEX idx ON orders (user_id, created_at); -- composite (leftmost — 2.5)
CREATE INDEX idx ON users (status) INCLUDE (ism, email); -- covering (2.6)
CREATE INDEX idx ON users (email) WHERE deleted_at IS NULL; -- partial (2.7)
CREATE INDEX idx ON users (LOWER(email)); -- functional (2.12)
-- EXPLAIN (2.9)
EXPLAIN ANALYZE SELECT ...; -- reja + haqiqiy vaqt
-- Keyset pagination (2.13)
WHERE id < $1 ORDER BY id DESC LIMIT 20; -- OFFSET o'rniga4. Batafsil misollar
Misol 1 — Indeks ta'siri (EXPLAIN bilan — 2.9)
-- Indekssiz (Seq Scan — 2.1)
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'ali@a.uz';
-- Seq Scan on users (cost=0..18000 rows=1) actual time=45ms SEKIN (full scan)
-- Indeks qo'shish
CREATE INDEX idx_users_email ON users (email);
-- Endi (Index Scan — 2.2)
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'ali@a.uz';
-- Index Scan using idx_users_email (cost=0..8 rows=1) actual time=0.05ms TEZ (900x!)Misol 2 — Composite indeks (to'g'ri tartib — 2.5)
-- So'rov: foydalanuvchining sana bo'yicha buyurtmalari
-- SELECT * FROM orders WHERE user_id = 5 ORDER BY created_at DESC;
-- To'g'ri composite (user_id — equality, created_at — sort; ESR — 2.5)
CREATE INDEX idx_orders ON orders (user_id, created_at DESC);
-- WHERE user_id + ORDER BY created_at — ikkalasi indeksdan (tez)
-- Noto'g'ri tartib (created_at, user_id) — WHERE user_id ishlatmaydi (2.5)Misol 3 — Covering index (2.6)
-- Tez-tez: SELECT ism, email FROM users WHERE status = 'faol';
CREATE INDEX idx_cover ON users (status) INCLUDE (ism, email);
EXPLAIN ANALYZE SELECT ism, email FROM users WHERE status = 'faol';
-- Index Only Scan (jadval O'QILMAYDI — eng tez — 2.6)Misol 4 — Partial index (2.7)
-- Admin panel: faqat kutilayotgan buyurtmalar (kichik qism)
CREATE INDEX idx_kutilmoqda ON orders (created_at)
WHERE status = 'kutilmoqda'; -- faqat shular indekslanadi
-- Bu so'rov partial indeksdan foydalanadi (tez, kichik indeks — 2.7)
SELECT * FROM orders WHERE status = 'kutilmoqda' ORDER BY created_at;Misol 5 — N+1 ni JOIN bilan tuzatish (2.11)
// N+1 (101 so'rov — 2.11)
const users = await pool.query("SELECT * FROM users LIMIT 100");
for (const u of users.rows) {
const o = await pool.query("SELECT * FROM orders WHERE user_id = $1", [u.id]); // har biriga!
u.orders = o.rows;
}
// Bitta JOIN (1 so'rov — 6.7)
const { rows } = await pool.query(`
SELECT u.id, u.ism, json_agg(o.*) AS orders
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id
LIMIT 100
`);
// json_agg — har user'ning buyurtmalarini massivga yig'adi (PostgreSQL)Misol 6 — Funksiya indeksni buzishi va functional index (2.12)
-- email indeksi BOR, lekin LOWER() uni ishlatmaydi (2.12)
CREATE INDEX idx_email ON users (email);
EXPLAIN ANALYZE SELECT * FROM users WHERE LOWER(email) = 'ali@a.uz';
-- Seq Scan (indeks ishlatilmadi — funksiya!)
-- Functional index (LOWER bo'yicha)
CREATE INDEX idx_email_lower ON users (LOWER(email));
EXPLAIN ANALYZE SELECT * FROM users WHERE LOWER(email) = 'ali@a.uz';
-- Index Scan (functional indeks ishladi — 2.12)Misol 7 — Keyset pagination (2.13)
// OFFSET (katta sahifada sekin — 2.13)
export const eskiUsul = (page) => pool.query(
"SELECT * FROM posts ORDER BY id DESC LIMIT 20 OFFSET $1", [(page - 1) * 20]
);
// Keyset (cursor — tez, cheksiz scroll — 2.13)
export const keyset = (oxirgiId) => pool.query(
oxirgiId
? "SELECT * FROM posts WHERE id < $1 ORDER BY id DESC LIMIT 20" // keyingi sahifa
: "SELECT * FROM posts ORDER BY id DESC LIMIT 20", // birinchi
oxirgiId ? [oxirgiId] : []
);
// Frontend oxirgi ko'rilgan id'ni saqlaydi, keyingi so'rovda yuboradiMisol 8 — Indekslarni tahlil qilish (PostgreSQL — 2.14)
-- Ishlatilmaydigan indekslarni topish (joy/yozish tejash — 2.14)
SELECT indexrelname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- hech ishlatilmagan o'chirish mumkin
-- Sekin so'rovlarni topish (pg_stat_statements kengaytmasi)
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
ORDER BY mean_exec_time DESC LIMIT 10; -- eng sekin 10 so'rov
-- Statistikani yangilash (optimizator uchun — 2.15)
ANALYZE users;5. To'g'ri va noto'g'ri holatlar
1) Tez-qidiriladigan ustunga indekssiz
email/user_id indekssiz Seq Scan (sekin — 2.1)
CREATE INDEX (Index Scan — 2.3)2) Composite indeks noto'g'ri tartib
-- (created_at, user_id) — WHERE user_id ishlatmaydi (2.5)
-- (user_id, created_at) — leftmost (2.5)3) Funksiya indekslangan ustunda
-- indeks ishlamaydi (2.12)
WHERE LOWER(email) = '...' -- email indeksi bekor
-- functional index yoki normallashtirilgan ma'lumot4) N+1 so'rov
tsiklda alohida so'rov (101 so'rov — 2.11)
JOIN/IN (1-2 so'rov)5) Katta OFFSET pagination
-- OFFSET 100000 (sekin — 2.13)
-- keyset (WHERE id < oxirgi)6) Hamma ustunga indeks
har ustunga indeks (yozish sekin, joy — 2.14)
faqat tez-qidiriladigan (EXPLAIN bilan tasdiqlangan)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — So'rov sekin (production)
Sababi: indekssiz Seq Scan 2.1-bob. Yechimi: EXPLAIN ANALYZE; WHERE ustuniga indeks 2.3-bob.
Xato 2 — Indeks qo'shdim, lekin ishlamayapti
Sababi: funksiya (LOWER — 2.12), noto'g'ri composite tartib 2.5-bob, yoki kichik jadval (optimizator Seq tanlaydi). Yechimi: EXPLAIN bilan tekshiring; functional index; tartibni to'g'irlang.
Xato 3 — Ilova o'sgan sari sekinlashdi
Sababi: jadval o'sdi, indekssiz so'rovlar 2.1-bob. Yechimi: sekin so'rovlarni topish (pg_stat_statements — Misol 8); indeks.
Xato 4 — INSERT/UPDATE sekinlashdi
Sababi: ortiqcha indekslar (har yozishda yangilanadi — 2.14). Yechimi: ishlatilmaydigan indekslarni o'chiring (Misol 8).
Xato 5 — N+1 (ORM'da yashirin)
Sababi: lazy loading (har element — so'rov — 2.11). Yechimi: eager loading (include/populate); JOIN.
Xato 6 — Sahifa raqami oshgani sayin sekin
Sababi: OFFSET 2.13-bob. Yechimi: keyset pagination (Misol 7).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Tree/Big-O (3.6, 3.1): B-tree, O(log n).
- MongoDB indeks 6.3-bob: bir xil tamoyil (B-tree, ESR).
- PostgreSQL 6.6-bob: GIN, partial, EXPLAIN.
- JOIN 6.7-bob: N+1, JOIN indeks.
- Normalizatsiya 6.9-bob: denormalizatsiya — optimizatsiya.
- Redis 5.21-bob: kesh — DB yukini kamaytirish.
- Materialized view 6.8-bob: og'ir hisobot keshlash.
- ORM 6.14-bob: N+1, eager loading.
- Monitoring 10.9-bob: sekin so'rov kuzatuvi.
8. Eng yaxshi amaliyotlar (best practices)
- WHERE/JOIN/ORDER BY ustunlariga indeks 2.4-bob; FK'ga ham 2.10-bob.
- Composite — to'g'ri tartib (leftmost, ESR — 2.5).
- Covering index (tez-tez, muhim so'rov — 2.6); partial (kichik qism — 2.7).
- EXPLAIN ANALYZE bilan o'lchang (taxmin qilmang — 2.9, 2.10).
- N+1 dan saqlaning (JOIN/IN/eager — 2.11).
- Funksiya indeksni buzadi (functional index — 2.12).
- Katta sahifalash — keyset (OFFSET emas — 2.13).
- Ortiqcha indeks emas (yozish narxi; ishlatilmaganni o'chiring — 2.14).
- SELECT kerakli ustunlar (covering imkoni — 2.12).
- Kesh/materialized view (og'ir/tez-o'qiladigan — 2.15, 5.21).
9. Amaliy loyiha: "DB Performance Optimizatsiya"
DB tezligini professional darajada mustahkamlash.
Maqsad
EXPLAIN bilan sekin so'rovlarni topib, indekslar va optimizatsiya bilan tezlashtirish (katta ma'lumotli e-commerce).
Talablar (requirements)
- Katta ma'lumot: ko'p qator (seed — 100K+) generatsiya qiling (test uchun).
- EXPLAIN tahlil: sekin so'rovlarni EXPLAIN ANALYZE bilan aniqlang (Seq Scan — Misol 1, 2.9).
- Indekslar: WHERE/JOIN/ORDER ustunlariga; oldin/keyin EXPLAIN solishtiring (Misol 1, 2.3).
- Composite: to'g'ri tartib (leftmost test — Misol 2, 2.5).
- Covering: tez-tez so'rovga INCLUDE (Misol 3, 2.6).
- Partial: kichik qism (kutilayotgan buyurtma — Misol 4, 2.7).
- N+1 tuzatish: tsikldagi so'rovni JOIN'ga (Misol 5, 2.11).
- Functional index: LOWER(email) (Misol 6, 2.12).
- Keyset pagination: OFFSET o'rniga (Misol 7, 2.13).
- Indeks audit: ishlatilmaydiganlarni toping (Misol 8, 2.14).
Maslahatlar (hint)
- EXPLAIN ANALYZE — oldin/keyin solishtiring (2.9, taxmin qilmang).
- Seq Scan (katta jadval) indeks (2.1, 1-xato).
- Composite: equality sort (ESR — 2.5).
- Funksiya functional index (2.12, 3-holat).
- N+1 JOIN/json_agg (Misol 5).
- OFFSET keyset (Misol 7).
- Ortiqcha indeks pg_stat (Misol 8).
"Tayyor" mezonlari (acceptance criteria)
- Katta ma'lumot bilan test.
- EXPLAIN ANALYZE bilan sekin so'rov topilgan.
- Indeks oldin/keyin tezlik farqi ko'rsatilgan.
- Composite to'g'ri tartib (leftmost).
- Covering index (Index Only Scan).
- Partial index.
- N+1 JOIN bilan tuzatilgan.
- Functional index (LOWER).
- Keyset pagination.
- Ortiqcha indeks tahlili.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda DB tezligi va optimizatsiyasini chuqur o'rgandik:
- Indekssiz — full scan (O(n), sekin — 2.1); indeks — B-tree (O(log n), tez — 2.2).
- Indeks turlari: yagona, composite (leftmost/ESR — 2.5), covering (INCLUDE — 2.6), partial (shart — 2.7), GIN/functional (2.8, 2.12).
- EXPLAIN ANALYZE (so'rov rejasi — Seq vs Index Scan, Filter vs Index Cond — 2.9, 2.10) — optimizatsiyaning kaliti.
- N+1 (JOIN/IN — 2.11); keyset pagination (OFFSET emas — 2.13); indeks narxi/balans 2.14-bob; kesh/materialized 2.15-bob.
Keyingi bob — 6.11-bob: ORM — Sequelize (model, relations, migration). Xom SQL (6.4-6.10) ni chuqur bildik; endi ORM (Object-Relational Mapping) ga o'tamiz — SQL'ni JS obyektlari bilan ishlash. Birinchi ORM — Sequelize: model, bog'lanishlar (relations), migration. ORM — produktivlikni oshiradi, lekin SQL bilimini talab qiladi (shuning uchun avval SQL'ni o'rgandik).
Foydalanilgan rasmiy/ishonchli manbalar
- OneUptime — PostgreSQL query optimization 2026 (EXPLAIN ANALYZE); Mydbops — indexing best practices
- AI2SQL — SQL indexing best practices (composite, covering); freeCodeCamp — how indexes work (B-tree)
- PostgreSQL docs — Indexes, EXPLAIN, pg_stat_statements
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!