Composite Index, Partial Index, Covering Index

~20 daq · PostgreSQL · Index va Performance

Bir ustunli index yetarli bo'lmagan holatlar bor. So'rovda doim ikki ustun birga filtrlanadi, yoki faqat ma'lum qatorlar uchun index kerak. Bu holatlarda maxsus index turlari yordam beradi.


Composite Index — bir nechta ustun

Bir nechta ustun birga filtrlanayotganda bitta composite index ikkitadan yaxshiroq:

-- Har ikkisi alohida — kam samarali
CREATE INDEX ON buyurtmalar (foydalanuvchi_id);
CREATE INDEX ON buyurtmalar (holat);

-- Birga — composite index
CREATE INDEX idx_user_holat ON buyurtmalar (foydalanuvchi_id, holat);
-- Bu so'rov composite indexdan to'liq foydalanadi
SELECT * FROM buyurtmalar
WHERE foydalanuvchi_id = 5 AND holat = 'kutilmoqda';

Tartib muhim

Composite indexda birinchi ustun har doim ishlatilishi kerak:

CREATE INDEX idx_a_b ON jadval (a, b);

WHERE a = 1 AND b = 2  -- ✅ ikkala ustun
WHERE a = 1            -- ✅ birinchi ustun
WHERE b = 2            -- ❌ birinchi ustunsiz ishlamaydi

Partial Index — shartli index

Jadvalning faqat bir qismi ko'p so'raladigan bo'lsa — faqat o'sha qism uchun index:

-- Barcha buyurtmalar uchun index — katta, sekin yangilanadi
CREATE INDEX ON buyurtmalar (yaratilgan);

-- Faqat "kutilmoqda" holatdagi buyurtmalar — kichik, tez
CREATE INDEX idx_kutilmoqda ON buyurtmalar (yaratilgan)
WHERE holat = 'kutilmoqda';

Endi bu so'rov kichik indexdan foydalanadi:

SELECT * FROM buyurtmalar
WHERE holat = 'kutilmoqda'
  AND yaratilgan > NOW() - INTERVAL '7 days';

Faol foydalanuvchilar — keng tarqalgan holat

-- Foydalanuvchilarning 5% admin — 95% oddiy user
-- Admin uchun alohida, kichik index
CREATE INDEX idx_adminlar ON foydalanuvchilar (email)
WHERE rol = 'admin';

Covering Index — INCLUDE

So'rov index orqali javob olishi uchun jadvalga murojaat qilishi kerak. INCLUDE bilan qo'shimcha ustunlar indexga qo'shilsa — jadvalga umuman murojaat bo'lmaydi (Index-Only Scan):

CREATE INDEX idx_email_covering ON foydalanuvchilar (email)
INCLUDE (ism, yosh);
SELECT ism, yosh FROM foydalanuvchilar WHERE email = 'j@mail.com';
-- Jadvalga murojaat yo'q — hammasi indexda!

INCLUDE ustunlar faqat qiymatni saqlash uchun — filtrlash, tartiblash uchun emas.


Functional Index — funksiya natijasiga index

Funksiya ichida ustun bo'lsa — oddiy index ishlamaydi. Funksiyaning natijasiga index:

-- Bu so'rovda oddiy index ishlamaydi
WHERE LOWER(email) = 'jasur@mail.com';

-- Yechim — functional index
CREATE INDEX idx_email_lower ON foydalanuvchilar (LOWER(email));
WHERE LOWER(email) = 'jasur@mail.com'; -- ✅ endi index ishlaydi

Tez-tez uchraydigan xatolar

Composite indexda noto'g'ri tartib:

CREATE INDEX ON buyurtmalar (holat, foydalanuvchi_id);

WHERE foydalanuvchi_id = 5; -- ❌ birinchi ustun holat, id emas
WHERE holat = 'kutilmoqda'; -- ✅

Ko'p filtrlangan ustun birinchi bo'lishi kerak.

Partial index shartiga mos kelmagan so'rov:

CREATE INDEX idx_kutilmoqda ON buyurtmalar (id) WHERE holat = 'kutilmoqda';

WHERE holat = 'bekor'   -- ❌ — partial index faqat 'kutilmoqda' uchun
WHERE holat = 'kutilmoqda' -- ✅

Xulosa

Composite   — bir nechta ustun birga filtrlanganda
              CREATE INDEX ON t (a, b);  — a birinchi bo'lishi shart

Partial     — faqat ma'lum qatorlar uchun
              CREATE INDEX ON t (a) WHERE b = 'x';

Covering    — jadvalga murojaatsiz javob
              CREATE INDEX ON t (a) INCLUDE (b, c);

Functional  — funksiya natijasiga index
              CREATE INDEX ON t (LOWER(a));

Keyingi dars

39-dars: EXPLAIN ANALYZE — query plan o'qish, Seq Scan vs Index Scan