GH GambleHub

Індексація аналітичних сховищ

1) Навіщо індексація iGaming-платформі

Швидкість аналітики: звіти по GGR/NET, конверсіям, RG/AML і A/B-експериментам укладаються в SLA.
Вартість: менше сканованих байт → нижче рахунок за обчислення/склад.
Надійність: стабільні p95/p99 латентності дашбордів і API метрик.
Масштаб: десятки брендів/ринків/PSP/провайдерів без «full scan» пекельної вартості.

2) Модель навантажень (перш ніж індексувати)

Факти: `payments`, `game_rounds`, `sessions`, `bonus_events`.
Вимірювання: `dim_user` (без PII), `dim_provider`, `dim_psp`, `dim_country`.
Запити: «останні N днів», агрегації по'brand/country/provider/psp', фільтри по статусовому полю, join'и по surrogate-keys, пошук по JSON-атрибутах (метод платежу, пристрій), top-K/percentile.

Вибираємо індекси, виходячи з селективності, кардинальності і частоти використання.

3) Типи індексів і коли їх брати

3. 1 Класика

B-tree: рівність/діапазони по високоселективних колонках ('user _ surrogate _ id','occurred _ at','amount').
Hash: чиста рівність; рідше в аналітиці (проти діапазонів слабкий).
Bitmap: низька кардинальність і часті з'єднані фільтри ('country','kyc _ level','rg _ state','brand'). Відмінні для підсумовування масок.

3. 2 Columnar-специфіка

Min-max (data skipping): автоматичні статистики «мінімум/максимум» в паркет-страйпах/частинах → движок пропускає блоки. Працює краще при сортуванні по фільтрованих полях.
Bloom-індекси: швидкі імовірнісні тести належності значення в блоці (корисні для'user _ id','transaction _ id','psp').
BRIN (Block Range Index): дешеві «покажчики» на діапазони блоків, якщо дані природно впорядковані (час). Дешево, але ефективно для time-series.

3. 3 Просунуті/спеціалізовані

GiST/GIN (інвертовані): JSON/arrays/текст, фільтри за вкладеними атрибутами ('metadata. method = 'Papara'`, `device. os in [...]`).
Join/Projection (ClickHouse/MPP): матеріали для прискорення join/agg (pre-join key зберігається поруч з фактом, попередні агрегації).
Векторні (ANN): пошук схожих ембеддингів (рекомендації/антифрод-поведінка) - IVF/HNSW/Flat як «індекс найближчих сусідів».
З-впорядкування/Z-order (lakehouse/Databricks )/Cluster keys (Snowflake )/ORDER BY (ClickHouse): багатовимірна кластеризація даних на диску для кращого data skipping.

4) Партіонування, сортування, кластеризація

Партії (date/country/brand): великі (день/тиждень), щоб уникнути «прокляття малих файлів». Вибираємо поля з високою селективністю в WHERE/права доступу.
Сортування всередині партії: 'ORDER BY (occurred_at, brand, psp)'або Z-order по'( brand, country, provider)'- так min-max і bloom відпрацьовують краще.
Cluster/Recluster: періодична перекластеризація для підтримки локальності.
TTL і ретеншн: автоматичне видалення старих партій/сегментів.

5) Матеріалізовані уявлення та проекції

MV для гарячих зрізів: `payments_7d_by_brand_psp`, `rounds_1d_by_provider`. Підтримуємо інкрементально (streaming upserts).
Проекції (ClickHouse )/Aggregate tables: попередні угруповання, roll-up рівні (chas→den→nedelya).
Кеш результатів: query result cache/warehouse result cache для повторюваних дашбордів (валідуємо по токену запиту і свіжості даних).

6) Напівструктуровані дані (JSON/VARIANT)

Індекси за шляхами: інвертовані/GIN-індекс на json-шляхах ('$ .device. os`, `$.psp. details. method`).
Матеріалізація важливих атрибутів у колонки: для стабільних фільтрів (метод платежу, пристрій, версія програми).
Статистики за ключами: збір дистрибуцій для селективного плану.

7) Озера даних: Iceberg / Delta / Hudi

Манifest-індекси: метадані про паркет-файли (min-max, null-count, bloom) → partition pruning + file skipping.
Компакція/об'єднання файлів: регулярний merge невеликих файлів в «оптимальний» розмір (128-1024 МБ).
Clustering/Z-order: перепакування файлів для корелюючих полів (наприклад,'brand, country, occurred _ at').
Delete/Update індекси: позиційні делти і bloom для прискорення merge-on-read.

8) Як вибирати індекси: Практичний чек-лист

1. Зберіть топ-N запитів (90% навантаження) → поля фільтрів/join/group.
2. Для кожного поля оцініть селективність'sel = 1 - distinct (value )/rows'і кардинальність.
3. Партія за часом + 1-2 вимірювання зі стабільними фільтрами/доступами.
4. Сортування/кластер keys узгодити з фільтрами і join-ключами.
5. Додайте bloom для точкових id, bitmap для низької кардинальності.
6. Гарячі агрегації → MV/проекції.
7. JSON-шляхи → інвертовані індекси + матеріалізація.
8. На озерах - компакція і clustering за розкладом.
9. Введіть SLO: p95-латентність, скановані байти/запит, частка skipped data.

9) Підтримка та обслуговування

ANALYZE/статистики: оновлюйте кардинальності та гістограми; інакше оптимізатор «сліпий».
VACUUM/OPTIMIZE/RECLUSTER: дефрагментація та перекластеризація.
Моніторинг використання індексів: «covering rate», «unused index list», «bytes scanned / bytes skipped».
Авто-порадники: періодичні рекомендації щодо кластер-ключів і сортувань на підставі query log.
Тести регресій: перед деплоєм нових ключів - порівняння профілю запитів і вартості.

10) Метрики і SLO індексації

Технічні: p95/p99 latency, scanned bytes/query, skipped bytes %, files touched, cache hit-rate.
Економіка: $/запит, $/дашборд, $/TB скана.
Операції: час компакції, черга перекластеризації, частка «малих файлів».
Якість планів: частка запитів, що використовують індекси/проекції, точність кардинальностей.

11) Кейси iGaming (готові рецепти)

11. 1 Платежі/PSP: падіння/відмови

Партія: `by day`. Сортування: `(brand, country, occurred_at)`.
Bloom: `transaction_id`, `user_id`. Bitmap: `psp`, `status`.
MV: `payments_7d_by_brand_psp(status, declines)`.
Результат: p95 ↓ з 8. 2s до 1. 1s, scanned bytes ↓ на 87%.

11. 2 Ігрові раунди: провайдер/гра

Z-order / ORDER BY: `(provider, game_id, occurred_at)`.
Projection/agg: `rounds_1d_by_provider_game`.
BRIN (якщо Postgres-подібне сховище): по `occurred_at`.
Результат: топ-K ігор/год - sub-second на гарячому кеші.

11. 3 RG/AML: події обмежень/самовиключень

Bitmap: `rg_state`, `kyc_level`. JSON-path GIN: `$.reason`.
MV: «активні обмеження за 30 днів» + матеріалізація user-рівня без PII.
Результат: швидкі вибірки для комплаєнсу без full scan мільярда подій.

11. 4 Антифрод: маршрути та пристрої

Матеріалізація JSON→kolonki: `device. os`, `device. model`, `payment. method`.
Bloom: `graph_device_id`. Cluster: `(brand, country, device. os)`.
Векторний індекс: ембеддинги «поведінка депозитів за 7д» → швидкий k-NN для схожих аномалій.

12) Безпека і приватність

Zero-PII в індексованих полях і логах планів.
Шифрування на диску: індекси/статистики шифруються так само, як дані.
K-анонімність агрегатів: MV/проекції публікують тільки групи ≥N.
Geo/tenant-ізоляція: партії/ключі включають'brand/country/license'.
Legal Hold: індекси/манівести теж потрапляють в «заморозку».

13) Анти-патерни

Індексувати «все підряд» → вибух об'єму і write-amplification.
Дрібні партії (година/хвилини) → шторм планок і «малі файли».
Ключі сортування, що не збігаються з фільтрами → нульовий data skipping.
Відсутність статистик → погані плани, full scan.
JSON без подорожніх індексів і без матеріалізації «гарячих» атрибутів.
Ігнор компакції і recluster → деградація через 2-4 тижні.

14) Шаблони (готово до використання)

14. 1 Політика кластеризації/індексації (YAML)

yaml dataset: gold. payments partition_by: ["date"]
order_by: ["brand","country","occurred_at"]
indexes:
bloom: ["transaction_id","user_surrogate_id"]
bitmap: ["psp","status","rg_state"]
materialized_views:
- name: mv_payments_7d_brand_psp group_by: ["brand","psp","status"]
window: "7d"
slo:
p95_latency_ms: 1200 scanned_bytes_per_query_max_mb: 256 maintenance:
compact_small_files: true recluster_cron: "0 /6  "
privacy:
pii_in_index: false

14. 2 План компакції озера (Iceberg/Delta)

yaml compaction:
target_file_size_mb: 512 small_file_threshold_mb: 64 zorder_by: ["brand","country","occurred_at"]
run_every: "PT6H"
max_concurrency: 4

14. 3 Індекси для JSON-полів

sql
-- GIN/inverted index on device attributes
CREATE INDEX idx_device_json ON gold. sessions
USING GIN ((device_json));
-- Materialization of critical pathways
ALTER TABLE gold. sessions ADD COLUMN device_os TEXT;
UPDATE gold. sessions SET device_os = device_json->>'os';
CREATE BITMAP INDEX idx_device_os ON gold. sessions(device_os);

14. 4 SLO моніторингу індексів

yaml monitoring:
skipped_bytes_share_min: 0. 70 index_usage_rate_min: 0. 85 stats_freshness_max_hours: 24 small_files_share_max: 0. 10

15) Дорожня карта впровадження

0-30 днів (MVP)

1. Збір топ-N запитів і профілів сканування.
2. Партіонування за датою + сортування, узгоджені з фільтрами.
3. Включити data skipping (min-max) і bloom для id-полів.
4. Один MV для «гарячої» метрики (payments 7d).
5. Дашборд SLI: p95, scanned bytes, skipped share, small files.

30-90 днів

1. JSON-шляхи: інвертовані індекси + матеріалізація.
2. Озеро: компакція і Z-order/clustering по 2-3 ключах.
3. Авторадник ключів/проекцій; регулярний ANALYZE.
4. Перегляд партій (day→week) там, де «малі файли».

3-6 місяців

1. Каталог MV/проекцій з версіонуванням і SLA.
2. Векторні індекси для рекомендацій/антифродів.
3. Єдина політика SLO і бюджетів $/запит; алерти деградацій.
4. Аудит приватності індексів, geo/tenant-ізоляція.

16) RACI

Data Platform (R): партії/індекси/компакції, авто-порадники, моніторинг.
Analytics/BI (R): MV/проекції під дашборди, профілювання запитів.
Domain Owners (C): критерії «гарячих» зрізів і фільтрів.
Security/DPO (A/R): приватність, PII-політики, geo/tenant-ключі.
SRE/Observability (C): SLO/алертинг, капасіті для компакцій.
Finance (C): бюджети $/запит і економія від індексів.

17) Пов'язані розділи

Схеми даних та їх еволюція, Валідація даних, DataOps-практики, Аналіз аномалій і кореляцій, API аналітики і метрик, Кластеризація даних, Зниження розмірності, MLOps: експлуатація моделей.

Підсумок

Індексація аналітичного сховища - це стратегія, а не «створити індекс на все». Правильні партії і сортування, data skipping і bloom, продумані MV/проекції і регулярна компакція дають швидкі і передбачувані запити при контрольованій вартості і без ризику для приватності. Для iGaming це означає оперативні рішення по платежах, провайдерам і RG/AML - в межах SLA і бюджету.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.