Soʻrovlarni indekslash va optimallashtirish
1) Indeksatsiya va optimallashtirish maqsadlari
Yashirin: P50/P95/P99 qisqartirish.
O’tkazish qobiliyati: gorizontal miqyossiz QPS o’sishi.
Oldindan aytish mumkin: barqaror rejalar va javob vaqtining «sakrashlari» yo’qligi.
Tejash: kam IO/CPU, kam bulut hisobi.
Ishonchlilik: to’g "ri kirish hisobiga blokirovka va dedloklarni kamaytirish.
- Har qanday maqbullashtirish toʻgʻrilik va muvofiqlikni saqlashi kerak.
- Metrik va reja loglarida effektni kuzatish.
2) Indekslarning bazaviy tuzilmasi va ularni qachon qo’llash
2. 1 B-Tree (defolt)
Teng/diapazonlar, saralash,’ORDER BY’.
Vaqt/ID/maqom boʻyicha koʻpgina filtrlar uchun yaxshi.
2. 2 Hash
Sof tengliklar (’=’), xotirada arzonroq, lekin tartibsiz (PG: cheklovlar olib tashlandi, lekin hali ham nish tanlash).
2. 3 GIN / GiST (PostgreSQL)
GIN: massivlar/JSONB kalitlari, toʻliq matn (tsvector), containment (’@>’).
GiST: geo, diapazonlar, kNN.
2. 4 BRIN (PostgreSQL)
Tabiiy ravishda saralangan stollar bo’yicha super-arzon indeks (append-only). Katta jadvalli time-series uchun yaxshi.
2. 5 Bitmap (MySQL/InnoDB: native emas; DW-SUBD/OLAP)
Kam kardinallik va fasetlar uchun samarali, ko’pincha kolonnali omborxonalarda.
2. 6 Ustunli indekslar (ClickHouse)
Primary key + data skipping (minmax), secondary через `skip indexes` (bloom, set).
OLAP soʻrovlari agregatsiyalar va diapazonlar bilan.
2. 7 Invertlangan indekslar (Elasticsearch/OpenSearch)
To’liq matn, fasetlar, gibrid qidiruv. Aniq filtrlar uchun keyword va doc values dan foydalaning.
2. 8 MongoDB
Single, compound, multikey (massivlar), partial, TTL, text, hashed (bir xil kalitli sharding uchun).
3) Kalitlar va kompozit indekslarni loyihalash
3. 1. «Chap prefiks» qoidasi
Indeksdagi maydonlarning tartibi foydalanishni belgilaydi.
’WHERE tenant_id =? AND created_at >=? ORDER BY created_at DESC` → индекс `(tenant_id, created_at DESC, id DESC)`.
3. 2 Tie-breaker
Barqaror saralash va seek-paginatsiya uchun oʻziga xos quyruq (odatda’id’) qoʻshing.
3. 3 Qisman/filtrlangan indekslar
Faqat «issiq» kichik turkumlarni indekslang:sql
CREATE INDEX idx_orders_paid_recent
ON orders (created_at DESC, id DESC)
WHERE status = 'paid' AND created_at > now() - interval '90 days';
3. 4 Qoplovchi indekslar
’Oʻqiladigan’ maydonlarni kiriting (MySQL:’INCLUDE’; PG 11+: `INCLUDE`):sql
CREATE INDEX idx_user_lastseen_inc ON users (tenant_id, last_seen DESC) INCLUDE (email, plan);
3. 5 Funksional/hisoblab chiqiladigan
Indeksdagi kalitlarni normallashtiring:sql
CREATE INDEX idx_norm_email ON users (lower(email));
4) Partiyalash va shardlash
4. 1 Partiyalashtirish (PG native/jadval merosi; MySQL RANGE/LIST)
Vaqt bo’yicha partiyalarning rotatsiyasi (’daily/weekly’)’VACUUM/DELETE’ni soddalashtiradi.
Mahalliy partiya indekslari → kichikroq B-Tree, tezroq reja.
sql
CREATE TABLE events (
tenant_id bigint,
ts timestamptz,
...
) PARTITION BY RANGE (ts);
4. 2 Partiyalash kaliti
OLTPda -’tenant _ id’bo’yicha (yuklamani mahalliylashtirish).
Time-series/OLAP’da - po’ts’(diapazonli so’rovlar).
Gibrid:’(tenant_id, ts)’+ subpartiyalar.
4. 3 Shardalashtirish
Consistent hashing/range-shard’tenant _ id’yoki vaqt boʻyicha.
Kross-shard so’rovi → scatter-gather va k-way merge; per-shard cursor.
5) Statistika, kardinallik va rejalar
5. 1 Dolzarb statistika
Avto- tahlilni kiriting (’autovacuum/autoanalyze’), «iflos» taqsimotlar uchun’default _ statistics _ target’ni kattalashtiring.
5. 2 Kengaytirilgan statistika (PG)
Bogʻlangan ustunlar:sql
CREATE STATISTICS stat_user_country_city (dependencies) ON country, city FROM users;
ANALYZE users;
5. 3. Bajarish rejasi
’EXPLAIN (ANALYZE, BUFFERS, VERBOSE)’ ga qarang; Asosiy maydonlar:- `Rows`, `Loops`, `Actual time`, `Shared Read/Hit`, `Recheck Cond`.
- Типы join: Nested Loop, Hash Join, Merge Join.
- Seq Scan vs Index Scan/Only Scan/Bitmap Heap Scan.
5. 4 Rejalarning barqarorligi
Parametrlash (prepared statements) yomon rejada «yopishib» qolishi mumkin. Rejadan foydalaning cache guardrails (PG:’plan _ cache _ mode = force_custom_plan' muammoli soʻrovlar uchun) yoki «boʻshash» doimiy.
6) Join-lar va saralashlarni optimallashtirish
6. 1 Strategiyalar
Nested Loop: kichik tashqi, ichki tezkor indeks.
Hash Join: katta toʻplamlar, hash table uchun yetarli xotira.
Merge Join: saralangan kirish, mavjud tartibda foydalidir.
6. 2 Join ostidagi indekslar
’A JOIN B ON B.a_id = A.id’ → uchun indeks’B (a_id)’ga.
Join filtri uchun - ichki jadvalning filtr ustunlaridagi indeks.
6. 3 Saralash
Tegishli indekssiz’ORDER BY’dan qoching; yo’lni xotira/disk bo’yicha katta to’plamlarda saralash.
7) So’rovlarni qayta yozish (query rewrite)
«Qor» so’rovlaridan xalos bo’ling; JOIN ga aylantiring.
CTE-inline (PG ≥ 12 inlines CTE ni andoza sifatida ishlating, lekin’MATERIALIZED’agar kerak boʻlsa oraliq natijani koʻrsatishi mumkin).
’SELECT’ ni olib tashlang → maydonlarni sanab oʻting (IO/tarmoqni tejash).
Hisoblashni’WHERE’dan indekslanadigan shaklga (oldindan belgilanadigan ustunlarga) koʻchiring.
Agregatsiyalar: inkremental yangilangan dastlabki jami jadvallar/materiallashtirilgan taqdimotlar.
8) Batching, limitlash va paginatsiya
Batch-insert/update: dona o’rniga 500-5000 dona.
Seek-paginatsiya’(sort_key, id)’o’rniga chuqur’OFFSET’.
Saralashdan/joydan oldin to’plamni limitlash (push-down’LIMIT’).
9) Keshlash va denormallashtirish
Dasturning query-cache darajasi (kalit = SQL + bind-vars + huquqlar versiyasi).
Materialized views uchun og’ir agregatlar; rotatsiya/refres rejasi.
Denormalizatsiya: tez-tez o’qiladigan hisoblab chiqiladigan maydonlarni (chegirmani hisobga olgan holda) saqlang, lekin konsistentlik uchun trigger/fon vazifasi bilan.
Redis L2 sifatida «issiq» kalitlar uchun (TTL va hodisalar bo’yicha nogironlik bilan).
10) Ommabop dvigatellarning o’ziga xosligi
10. 1 PostgreSQL
Индексы: B-Tree, Hash, GIN/GiST, BRIN, partial, functional, INCLUDE.
Misol:sql
CREATE INDEX idx_orders_tenant_created_desc
ON orders (tenant_id, created_at DESC, id DESC)
INCLUDE (amount, status);
Toʻliq matn:
sql
CREATE INDEX idx_docs_fts ON docs USING GIN (to_tsvector('russian', title ' ' body));
10. 2 MySQL/InnoDB
Kompozit, qamrab oluvchi indekslar (maydonlarni kalitga kiritish hisobiga), testlar uchun ko’rinmas indekslar:sql
ALTER TABLE orders ALTER INDEX idx_old INVISIBLE; -- check risk-free plans
Gistogrammalar bo’yicha statistika (’ANALYZE TABLE... UPDATE HISTOGRAM` в 8. 0).
10. 3 ClickHouse
Birlamchi kalit = saralash;’ORDER BY (tenant_id, ts, id)’.
O’tkazish indekslari:sql
CREATE TABLE events (
tenant_id UInt64,
ts DateTime64,
id UInt64,
payload String,
INDEX idx_bloom_payload payload TYPE bloom_filter GRANULARITY 4
) ENGINE = MergeTree()
ORDER BY (tenant_id, ts, id);
10. 4 MongoDB
Kompozit/multikalar: tartib muhim, filtr va saralash indeks bilan mos kelishi kerak:js db. orders. createIndex({ tenant_id: 1, created_at: -1, _id: -1 });
db. orders. createIndex({ status: 1 }, { partialFilterExpression: { archived: { $ne: true } } });
Diagnostika uchun’hint ()’dan foydalaning va’covered query’ga amal qiling.
10. 5 Elasticsearch/OpenSearch
Keyword vs text maydonlari; doc_values/agregatlarni saralash.
Segmentatsiya heap: agregatsiyalar - heavy; ’size’ ni cheklang va’composite’dan foydalaning.
Analizatorlarni aniq taqqoslash kerak boʻlgan joylarda yoqmang.
11) Raqobatbardoshlik, blokirovka va MVCC
Qisqa tranzaksiyalar; «REPEATABLE READ» ostida «uzoq» o’qishdan ehtiyot bo’ling.
Indeks operatsiyalari ham blokirovka qiladi (write throughput pasayishi).
Onlayn indeksatsiya qilishni rejalashtiring:’CREATE INDEX CONCURRENTLY’(PG),’ALGORITHM = INPLACE ’/’ ONLINE’(MySQL).
/ ID → indeksning «qaynoq sahifalari» ga qo’shimchalar; kalit (UUIDv7/tuz).
12) Kuzatuv va SLO
Metriklar:- ’db _ query _ latency _ ms’ (P50/P95/P99) soʻrov nomi boʻyicha.
- `rows_examined`, `rows_returned`, `buffer_hit_ratio`.
- `deadlocks`, `lock_wait_ms`, `temp_sort_disk_usage`.
- ’Index Scan’ kutilgan joydagi’Seq Scan’bilan rejalar ulushi.
- DBX versiyasi/parametrlarini o’zgartirishda regress-alertlar.
- Chegarasi 200 ms boʻlgan slow query logni kiriting.
- Soʻrovlarni spanlar bilan bogʻlash (trace_id).
- Muammoli soʻrovlar rejalarini olib tashlang va retrospektiv uchun obʼekt omboriga saqlang.
- O’qish P95’<= 150 ms’bilan’LIMIT <= 50’va «issiq» tenant.
- 1000 satrgacha batchlarda’<= 200 ms’yozuvlar P95.
13) Xavfsizlik va ko’p tenantlik
Kirish nazorati bo’yicha indekslar (’tenant _ id’,’owner _ id’) majburiydir.
Siyosatlar (RLS/ABAC) pre-filter boʻlishi kerak; aks holda optimallashtiruvchi noto’g’ri rejalashtirmoqda.
Sezgir maydonlarni ochiq koʻrinishda indekslamang; xesh/tokenlardan foydalaning.
14) Anti-patternlar
Seek-kursor muqobilisiz chuqur’OFFSET’.
«Hamma narsaga bitta indeks» - xotirani ortiqcha yuklash va write-path.
«SELECT» tanqidiy yo’llarda.
’WHERE’ ustunidagi funktsional indekssiz funksiyalar.
Eski statistika tufayli notinch rejalar.
Barqaror tartibni kutishda’ORDER BY’ning yo’qligi.
Indekslar uchun indekslar: ROI <0
15) Joriy etish chek-varaqasi
1. QPS va vaqt bo’yicha Top-N so’rovlar → 3-5 nomzodni tanlash.
2. ’EXPLAIN ANALYZE’ rejalarini bekor qilish, kardinallikni tekshirish vs haqiqiy.
3. Indekslarni loyihalash: maydon tartibi, INCLUDE/partial/functional.
4. Katta jadvallar uchun partiyalashtirishni joriy etish (vaqtinchalik/tenant kalitlar).
5. So’rovlarni qayta yozish:’SELECT’ni olib tashlash, oddiy CTE’ni uzish, to’plamni cheklash.
6. Batching va seek-paginatsiyani yoqish.
7. Keshni moslash: L1/L2, hodisalar boʻyicha nogironlik.
8. Rejalar va slow-log monitoringini, regress alertlarini joriy etish.
9. Ma’lumotlarni real taqsimlagan holda yuklama testlarini o’tkazish.
10. Ishlab chiqish uchun gidlaynlarni yangilash (ORM-xintlar, indeksatsiya, limitlar).
16) «oldin/keyin» misollari
Gacha:sql
SELECT FROM orders
WHERE status = 'paid'
ORDER BY created_at DESC
LIMIT 50 OFFSET 5000;
Keyingi:
sql
-- Индекс: (status, created_at DESC, id DESC) INCLUDE (amount, currency)
SELECT id, amount, currency, created_at
FROM orders
WHERE status = 'paid'
AND (created_at, id) < (:last_ts,:last_id) -- seek
ORDER BY created_at DESC, id DESC
LIMIT 50;
17) ORM va API protokollari
N + 1 dan qoching: ochkoʻzlik namunalari (’includes’,’JOIN FETCH’,’preload’).
Maydonlarning aniq proyeksiyalari, paginate kursor.
gRPC/REST:’page _ size’ni cheklang,’sort’ni belgilang, shaffof boʻlmagan tokenlardan foydalaning.
Reja-kesh: parametrlashdan foydalaning; har bir chaqiruvga «noyob» SQL yaratmang.
18) Migratsiya va ekspluatatsiya
Onlayn indekslarni qo’shing va INVISIBLE/CONCURRENTLY sifatida belgilang, rejalarni sinab ko’ring, keyin almashtiring.
Indekslar taftishi - muntazam sanitariya jihatidan tozalash: eski sahifa uchun «o’lik», foydalanilmayotgan dublikatlar.
Partiyalar rotatsiyasi rejasi (eski) va «VACUUM/OPTIMIZE» jadvali.
19) Xulosa
So’rovlarni optimallashtirish - bu tizim muhandisligi: to’g "ri kalitlar va indekslar, ehtiyotkorlik bilan rejalar, o’ylangan partiyalashtirish va shardlashtirish, so’rovlarda tartib-intizom va ORM, keshlash va kuzatish. Tavsiflangan namunalarga rioya qilsangiz, tezkor, bashorat qilinadigan va tejamkor, ma’lumotlar va yukning o’sishiga chidamli tizimga ega bo’lasiz.