Analitik sorğuların optimallaşdırılması
1) Niyə optimallaşdırmaq (iGaming konteksti)
Biznes sürəti: GGR/NET hesabatları, provayderlər/oyunlar, RG/AML və marketinq p95 SLA.
Qiymət: daha az taranan bayt və shafla → aşağı $/sorğu.
Etibarlılıq: sabit pik saat, heç bir «dondurma» BI.
Miqyaslı: onlarla marka/bazar, milyardlarla sətir, dəqiqələr təzəlik.
2) Yükləmə profili və SLO
«İlk 90%» sorğularını təsvir edin: pəncərələr (7/28/90d), filtrlər ('brand, country, provider, psp, status'), join 's, JSON atributları, top K və üzlük.
SLO nümunələri: p95 ≤ 1. 2 s dashboard, scanned bytes ≤ 256 MV/sorğu, freshness ≤ 5 min.
3) Planların anatomiyası: nə axtarmaq lazımdır
Predicate/Projection pushdown: filtrlər və sütunlar siyahısı mənbəyə endirilir.
Partition pruning & data skipping: əlavə partiyalar/fayllar kəsmək (min-max/bloom/manifest).
Vectorized scan/late materialization: JOIN/PROJECT tərəfindən təxirə salınmış sütun oxu.
Join strategy: Broadcast Hash (BHJ), Sort-Merge (SMJ), Nested Loop (NLJ — избегать).
Spill & shuffle: qarışdırma həcmi və diskə tökülməsi SLA-nın əsas düşmənidir.
Adaptive query execution: ranttime strategiya dəyişikliyi (BHJ SMJ keçid, dinamik koalits).
Plan göstərməlidir: nə qədər bayt oxuyuruq, harada zəfərliyik, nəyi keşikləyirik.
4) Partiyalar, çeşidləmə, klaster-keys
Partisia: 'date' + 1-2 giriş ölçüsü (məsələn, 'brand, country').
Sıralama/klasterləşdirmə: 'ORDER BY/CLUSTER BY/Z-order' tez-tez süzgəclər/joins ('provider, game_id, occurred_at').
Reclasterization və kompaksiya: data skipping üçün müntəzəm üst-üstə; hədəf fayl ölçüsü 128-1024 MB.
5) JOIN nümunələri
Broadcast Hash Join (BHJ): kiçik ölçü (≤ yüzlərlə MB) → fakt üçün broadcast.
sql
/ hint if engine supports/
SELECT /+ BROADCAST(dim_provider) /...
Sort-Merge Join (SMJ): böyük dəstlər, uyğun açar çeşidləmə/klaster-cases → minimum şafl.
Pre-join/denormalizasiya: sabit atributları 'dim _' -dən fakt-görüntüyə (projection/materialized view) - kritik yolda mənfi JOIN.
Anti/semijoins: 'NOT IN/EXISTS' açıq semi-/anti-join planlarına yenidən yazın.
Kardinal partlayışın aradan qaldırılması: ölçmələrdə təkrarlanan açarları yoxlayın, surrogate-keys istifadə edin.
6) GROUP BY, aqreqatlar və əvvəlcədən aqreqasiya
Rollup/Cube/Grouping Sets: bir mərhələ bir neçə aqreqasiya əvəzinə.
sql
SELECT brand, country, DATE(ts) d, SUM(amount)
FROM gold. payments
WHERE ts >= NOW() - INTERVAL '7 days'
GROUP BY GROUPING SETS ((brand,country,d),(brand,d),(d));
Materiallaşdırılmış təqdimatlar (MV )/proyeksiyalar: 'payments _ 7d _ by _ brand _ psp', 'rounds _ 1d _ by _ provider _ game'.
Partial → Final aggregation: Mühərrikin qismən workers (local) və nəhayət koordinator üzərində yığılmasına icazə verin.
Approximate: HLL üçün 'COUNT (DISTINCT user)', TDigest - dəfələrlə ucuz və BI üçün kifayətdir.
7) Pəncərə funksiyaları (səliqəli)
PARTITION BY yüksək seçicilik ilə düz açarlar; ORDER BY - sütunlu çeşidləmə üzrə.
Ağır pəncərələri mümkün olan pre-aqreqatlar və semi-joins ilə əvəz edin.
sql
-- Instead of window distinct
SELECT brand, COUNT() users
FROM (SELECT DISTINCT brand, user_id FROM gold. sessions WHERE d>=CURRENT_DATE-7) t
GROUP BY brand;
8) Filtrlər, paginasiya və TOP-K
Filter qaydası CBO üçün vacib deyil, lakin seçicilik və indekslər/çeşidləmə vacibdir.
LIMIT … WITH TIES/APPROX TOP-K - scan qısaldılır.
Pagination: böyük cədvəllər üçün 'OFFSET/LIMIT' əvəzinə 'keyset pagination'.
sql
-- keyset
SELECT FROM t WHERE (date, id) > (:last_date,:last_id) ORDER BY date, id LIMIT 1000;
9) JSON/yarı strukturlu
Sütunlara isti yolları materiallaşdırın ('device. os`, `psp. method`).
Mühərrik dəstəkləsə, JSON yollarında çevirilmiş indekslər/GIN istifadə edin.
Sətirlərdə UDF-dən çəkinin: atributların seçilməsi ilə daha yaxşı proyeksiya.
10) Approx və sampling
HLL/Theta Sketch: ucuz 'COUNT DISTINCT'.
TDigest/KLL: tam sort olmadan p95/p99 üzlük.
Reservoir/stratified sampling: interaktiv tədqiqat və preview.
11) Yaddaş, boğaz və konkarrensi
Spill-guard: join/agg yaddaş limitləri; boğazda - batch/parallelism azaldın, açar sıralamasını artırın.
Concurrency & QoS: «isti» dashboard və ağır ad-hoc üçün hovuzlar; skan/vaxt limitləri; «unudulmuş» sorğulara kill-switch.
Result cache/query cache: təkrarlanan BI şablonları üçün daxil edin, təravət tokenini əlil edin.
12) Reqressiya və «ikiqat qaçış» testləri
Top-N sorğular üçün istinad profillərini (plan/tarama-bayt/vaxt) saxlayın.
İndeks/klasterlərin buraxılmasından əvvəl - A/B-qaçışı: p95, scanned bytes, skipped share, shuffle ilə müqayisə edin.
«Fail-fast» eşikləri yaradın: p95 artıbsa> X% - geri dönüş.
13) Müşahidə və SLO
SLI:- p50/p95/p99 latency, scanned bytes/query, skipped bytes %, files touched;
- shuffle bytes, spilled bytes, peak memory;
- cache hit-rate; accuracy approx aqreqatları.
Alerts: scanned bytes artım, skipped paying, tez-tez NLJ, boğaz> eşik.
14) iGaming Cases (reseptlər)
14. 1 Ödənişlər/PSP: «uğursuzluq zirvələri»
WHERE: `ts BETWEEN now()-7d AND now()`, `brand,country,psp,status`.
Partiya: day; ORDER/Z-order: `(brand,country,ts)`; bitmap: `psp,status`; bloom: `transaction_id`.
MV: `payments_7d_by_brand_psp(status)`.
Nəticə: p95 → ~ 1s, scanned bytes ↓ 5-10 ×, sıfır boğaz.
14. 2 Oyun raundları: Top K oyunları/saat
ORDER BY / cluster по `(provider, game_id, occurred_at)`; pre-aqreqatlar üçün projection.
Approx Top-K + TDigest p95 raund müddəti üçün.
Nəticə: isti keşdə alt saniyəlik qrafiklər.
14. 3 RG/AML: aktiv məhdudiyyətlər
JSON 'reason' → sütun; bitmap `rg_state`, `kyc_level`; semi-join son vəziyyəti ilə.
Nəticə: «30 gün» hesabatı - saniyələrlə, tam scan olmadan.
15) Optimizasiya çek siyahısı (gündəlik)
1. Top-N sorğuların və onların profillərinin toplanması (plan/bayt/şafl).
2. Partiya tarixinə görə + razılaşdırılmış çeşidləmə/klaster-keys.
3. Test pushdown və pruning projection (yalnız lazımi sütunlar).
4. JOIN strategiyası: kiçik broadcast, SMJ üçün çeşidləmə, NLJ yoxdur.
5. Hot dashboard üçün ön aqreqasiya/MV.
6. Approx harada icazə verilir (distinct/percentiles/top-k).
7. JSON → sütunlar və/və ya invertasiya indeksləri.
8. Kompaksiya/reklasterləşdirmə; skipped bytes hədəf ≥ 70%.
9. Cache nəticələr və ayrı-ayrı konkarrensi hovuzları.
10. Monitorinq: p95, scanned bytes, shuffle, spill, hit-rate.
16) Şablonlar (istifadəyə hazır)
16. 1 Optimallaşdırma Siyasəti (YAML)
yaml workload: bi_hot slo:
p95_latency_ms: 1200 scanned_bytes_max_mb: 256 skipped_bytes_share_min: 0. 70 storage:
partition_by: ["date"]
cluster_by: ["brand","country","occurred_at"]
indexes:
bloom: ["transaction_id","user_surrogate_id"]
bitmap: ["psp","status","rg_state"]
aggregation:
mv:
- name: mv_payments_7d_brand_psp window: "7d"
group_by: ["brand","psp","status"]
approx:
count_distinct: "hll"
percentile: "tdigest"
concurrency:
pools: {bi_hot: 50, adhoc: 10}
timeout_s: 120
16. 2 Sorğu reqressiya testi (psevdo-SQL)
sql
-- baseline: p95<=1200ms, scanned_bytes<=256MB
EXPLAIN ANALYZE
SELECT brand, psp, status, COUNT() cnt, SUM(amount) amt
FROM gold. payments
WHERE ts >= NOW() - INTERVAL '7 days'
AND brand =:brand AND country =:country
GROUP BY brand, psp, status;
16. 3 DISTINCT yenidən yazılması
sql
-- Bad: Heavy COUNT (DISTINCT user_id)
SELECT COUNT(DISTINCT user_id) FROM gold. sessions WHERE d>=CURRENT_DATE-7;
-- Better: HLL sketch/preaggregate
SELECT hll_union(user_hll) FROM agg. sessions_7d_user_hll WHERE d>=CURRENT_DATE-7;
16. 4 Keyset Pagination
sql
SELECT
FROM gold. game_rounds
WHERE (occurred_at, round_id) > (:ts,:rid)
AND brand=:brand AND country=:country
ORDER BY occurred_at, round_id
LIMIT 1000;
17) Anti-nümunələr
'SELECT' prodda; heç bir projection pruning.
Milyonlarla sətirdə OFFSET paginasiyası.
COUNT DISTINCT eskizsiz; tam sort.
Böyük dəstlərdə NLJ; JSON ifadələri ilə join.
Kiçik partisiyalar və parçalanmış fayllar (metadata fırtınası).
Hoparlörləri materiallaşdırmaq əvəzinə, WHERE-də UDF sətirləri.
İqnor statistik/ANALYZE - kor optimallaşdırıcı və tam scan.
Reqressiya testlərinin və geri dönmə həddinin olmaması.
18) Tətbiqi yol xəritəsi
0-30 gün (MVP)
1. Top N sorğuları ölçmək və SLO/SLI quraşdırılması.
2. Partiya tarixinə görə + çeşidləmə/klaster-keys; data skipping/bloom.
3. Ödənişlər üzrə «isti» hesabata bir MV; HLL/TDigest в BI.
4. Sorğu hovuzlarının ayrılması, result cache-nin daxil edilməsi.
30-90 gün
1. Ağır pəncərələrin siyahıyaalınması/JSON → ön birləşmə/sütun.
2. Broadcast-join kiçik ölçülü; böyük üçün SMJ; NLJ aradan qaldırılması.
3. Cədvəl üzrə kompaksiya və reklasterləşdirmə; avtomatik açar məsləhətçisi.
4. Müşahidə və deqradasiya alertləri, A/B planları, avtomatik geri çəkilmə.
3-6 ay
1. Version və SLA ilə/MV proyeksiya kataloqu.
2. Approx bütün dashboard distinct/percentile/top-k üçün nüvə.
3. Vahid reqres test şablonları və $/sorğu büdcələri.
4. JSON və UDF daimi gigiyenası: materiallaşma və indekslər.
19) RACI
Data Platform (R): partiyalar/klasterləşdirmə/kompaksiya, MV/proyeksiyalar, caches, monitorinq.
Analytics/BI (R): SQL yenidən yazılması, approx aqreqatları, reqressiya testləri.
Domain Owners (C): kəsmə və dəqiqlik tələbləri.
Security/DPO (A/R): gizlilik/PII, k-anonimlik aqreqatları.
SRE/Observability (C): SLO/alerting, konkarrensi və kapasiti.
Finance (C): $/sorğu üçün büdcələr və iqtisadi effekt.
20) Əlaqəli bölmələr
Analitik anbarların indeksləşdirilməsi, Verilənlər sxemləri və onların təkamülü, Verilənlərin validasiyası, DataOps təcrübələri, Verilənlərin klasterləşdirilməsi, Ölçünün azaldılması, API analitikası və metrikası, MLOps: modellərin istismarı.
Yekun
Sorğuların optimallaşdırılması «sehrli hint» deyil, bir sistemdir: məlumatların səlahiyyətli işarələnməsi (partisia/klaster), əvvəlcədən yığılma və approximate-alqoritmlər, düzgün JOIN strategiyaları, cache/konkarrensi və daimi monitorinq p95 və scanned bytes. iGaming üçün bu, SLA və büdcə çərçivəsində ödənişlərin, oyunların və uyğunluğun sürətli və sabit metrikləri deməkdir.