GH GambleHub

Otimizar consultas analíticas

1) Por que otimizar (contexto iGaming)

Velocidade de negócios: relatórios GGR/NET, provedores/jogos, RG/AML e marketing em p95 SLA.
Valor: menos bytes de escaneamento e safra → abaixo de $/consulta.
Confiabilidade: relógio de pico estável, falta de «congelamento» BI.
Escala: dezenas de marcas/mercados, bilhões de linhas, minutos de frescura.

2) Perfil de carga e SLO

Descreva «primeiros 90%» dos pedidos: janelas (7/28/90d), filtros ('brand, country, provider, psp, status'), join's, atributos JSON, top K e percentil.
SLO exemplos p95 ≤ 1. 2 s para dashbord, scanned bytes ≤ 256 MV/consulta, freshness ≤ 5 min.

3) Anatomia de planos: o que procurar

Predicate/Project pushdown: os filtros e a lista de colunas são baixados para a origem.
Partition pruning & data skipping: corte de partituras/arquivos extras (min-max/bloom/manifest).
Vectorized scan/late materialização: leitura por colunas postergadas pelo JOIN/PROJECT.
Join strategy: Broadcast Hash (BHJ), Sort-Merge (SMJ), Nested Loop (NLJ — избегать).
Spill & shuffle: Volume e estreito em disco é o maior inimigo do SLA.
Adaptative query exation: mudança de estratégia no RAT (mudança de BHJ↔SMJ, coligação dinâmica).

O plano tem de mostrar quantos bytes lemos, onde é que estamos a bater, o que estamos a esconder.

4) Partições, arrumações, maletas de cluster

Partições: por 'data' + 1-2 medidas de acesso (por exemplo, 'brand, country').
Triagem/clusterização: 'ORDER BY/CLUSTER BY/Z-order' por filtros/joins frequentes ('provider, game _ id, accurred _ at').
Reclasterização e compactação: translado regular para o data skipping; tamanho alvo dos arquivos 128-1024 MB.

5) JOIN-pattern

Broadcast Hash Join (BHJ): pequena dimensão (≤ de cem MB) → broadcast para o fato.

sql
/ hint if engine supports/
SELECT /+ BROADCAST(dim_provider) /...

Sort-Merge Join (SMJ): conjuntos grandes, arrumações-chave compatíveis/maletas de cluster → safra mínima.
Pré-join/denormalização: leve os atributos estáveis de 'dim _' para um dado-foto (project/materialization view) - menos o JOIN no caminho crítico.
Anti/semijoins: troque 'NOT IN/EXISTs' para planos explícitos semi-/anti-join.
Resolver uma explosão radical: verifique as chaves duplicadas nas dimensões, use surrogate-keys.

6) GROUP BY, equipamentos e pré-agremiações

Rollup/Cube/Grouping Sets: uma fase em vez de várias unidades.

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));

Apresentações materializadas (MV )/projeções: 'payments _ 7d _ by _ brand _ psp', 'rounds _ 1d _ by _ provider _ game'.
Partial → Final aggregation: Deixe o motor adicionar em parte dos workers (local) e finamente no coordenador.
Approximate: HLL para 'COUNT (DISTINCT user)', TDigest para percentilos é duas vezes mais barato e suficiente para BI.

7) Funções de janela (com cuidado)

PARTITION BY exatamente pelas chaves de alta seletividade; ORDER BY - por ordem invertebrada.
Substitua as janelas pesadas por pré-regatas e semi-joins sempre que possível.

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) Filtros, paginação e TOP-K

A ordem dos filtros não é importante para o CBO, mas a seletividade e os índices/triagem são importantes.
LIMIT … WITH TIES/APPROX TOP-K - Encurtam a rocha.
Paginação: 'keyset pagination' em vez de 'OFFSET/LIMIT' para grandes tabelas.

sql
-- keyset
SELECT FROM t WHERE (date, id) > (:last_date,:last_id) ORDER BY date, id LIMIT 1000;

9) JSON/meio estruturado

Materialize os caminhos quentes nas colunas ('device. os`, `psp. method`).
Use os índices invertidos/GIN nos caminhos JSON se o motor suporta.
Evite o UDF por linha: melhor projeção com atribuição de atributos.

10) Approx e samplicação

HLL/Theta Sketch: barato 'COUNT DISTINCt'.
TDigest/KLL: Percentaram p95/p99 sem full sort.
Reservoir/stratied sampling: pesquisa interativa e exaltação.

11) Memória, estreito e concarrense

Spill-guard: limites de memória para join/agg; no estreito - reduza o batch/paralelismo e aumente a triagem por chave.
Concurrency & QoS: balas para dashboards «quentes» e pesados ad-hoc; limites de scan/hora; kill-switch para pedidos «esquecidos».
Result cache/query cache: inclua para modelos BI repetíveis, inválida pelo token de frescura.

12) Testes de regressão e «duplo teste»

Guarde os perfis de referência (plano/scan bytes/hora) para as consultas top N.
Antes de lançar os índices/clusters - A/B-teste: compare p95, scanned bytes, skipped share, shuffle.
Crie um limiar «fail-fast»: se o p95 cresceu> X% - retrocesso.

13) Observabilidade e SLO

SLI:
  • p50/p95/p99 latency, scanned bytes/query, skipped bytes %, files touched;
  • shuffle bytes, spilled bytes, peak memory;
  • cache hit-rate; accuracy approx equipamentos.

Alerts: Crescimento scanned bytes, queda skipped share, frequentes NLJ, estreito> limiar.

14) Mala de iGaming (receitas)

14. 1 Pagamentos/PSP: «picos de rejeição»

WHERE: `ts BETWEEN now()-7d AND now()`, `brand,country,psp,status`.
Partição: day; ORDER/Z-order: `(brand,country,ts)`; bitmap: `psp,status`; bloom: `transaction_id`.
MV: `payments_7d_by_brand_psp(status)`.
Resultado: p95 → £1s, scanned bytes ↓ em 5-10 x, estreito zero.

14. 2 Rodadas de jogos: top K jogos/hora

ORDER BY / cluster по `(provider, game_id, occurred_at)`; projecção para pré-regatas.
Approx Top-K + TDigest para a duração da rodada.
O resultado são gráficos de segundo segundo segundo segundo em um cofre.

14. 3 RG/AML: restrições ativas

JSON 'reason' → coluna; bitmap `rg_state`, `kyc_level`; semi-join com o último estado.
Resultado: relatório de 30 dias - segundos, sem full scan.

15) Folha de cheque de otimização (diária)

1. Coleta os pedidos top N e seus perfis (plano/bytes/safra).
2. Partições por data + arranjos/maletas de cluster acordados.
3. Verificar pushdown e project pruning (somente as colunas desejadas).
4. Estratégia JOIN: broadcast pequenos, triagem para SMJ, sem NLJ.
5. Pré-regulação/MV para dashboards quentes.
6. Approx onde é permitido (distinct/percentiles/top-k).
7. JSON colunas e/ou índices invertidos.
8. Compactação/reclasterização; alvo de skipped bytes ≥ 70%.
9. A caixa de resultados e as balas de concarrensia separadas.
10. Monitoramento: p95, scanned bytes, shuffle, spill, hit-rate.

16) Modelos (pronto para uso)

16. 1 Política de otimização (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 Teste de regressão de consulta (pseudo-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 Reescrever o DISTINCT

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 paginação Keyset

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-pattern

'SELECT' em venda; falta do project pruning.
Paginação OFFSET em milhões de linhas.
COUNT DISTINCT sem esquetes; percentaram através de um porto completo.
NLJ em grandes conjuntos; join pelas expressões JSON.
Pequenas partições e arquivos esparsos (tempestade de metadados).
Linhas UDF no WHERE em vez de materializar colunas.
Estatístico ignorado/ANALYZE - Otimizador cego e full scan.
Não há testes de regressão ou liminares de retração.

18) Mapa de trânsito de implementação

0-30 dias (MVP)

1. Medir o top N de solicitações e instalar o SLO/SLI.
2. Partições por data + triagem/mala de cluster; incluir o data skipping/bloom.
3. Um MV para relatório de pagamento «quente»; HLL/TDigest в BI.
4. Separação de pool de consulta, ativação de result cache.

30 a 90 dias

1. Censo de janelas pesadas/JSON → pré/coluna.
2. Broadcast-join pequenas dimensões; SMJ para grandes; eliminar NLJ.
3. Compactação e reclasterização programada; O conselheiro automático das chaves.
4. Observabilidade e alertas de degradação, planos A/B, auto-recall.

3-6 meses

1. Catálogo de projeções/MV com versioning e SLA.
2. O núcleo Approx para distinct/percentile/top-k em todos os dashboards.
3. Modelos de testes de regresso e orçamentos $/consulta.
4. Higiene permanente JSON e UDF: materialização e índices.

19) RACI

Data Platford (R): partituras/clusterização/compactação, MV/projeções, cachês, monitoramento.
Analytics/BI (R): reescrever SQL, aparatos approx, testes de regressão.
Domain Owners (C): requisitos de corte e precisão.
Segurança/DPO (A/R): privacidade/PII, k-anonimato das unidades.
SRE/Observabilidade (C): SLO/alerting, concarrense e capasiti.
Finance (C): orçamentos para $/pedido e impacto econômico.

20) Seções relacionadas

Indexação de armazenamento analítico, Circuitos de Dados e sua evolução, Validação de Dados, Práticas de Exploração de Dados, Clusterização, Redução de Dimensões, API Analistas e Métricas, MLOs: Operação de Modelos.

Resultado

A otimização das consultas não é um «hint mágico», mas sim um sistema de sinalização de dados (partições/cluster), pré-agremiação e aproximate-algoritmos, estratégias JOIN corretas, dinheiro/concarrance e monitoramento contínuo p95 e scanned bytes. Para iGaming, isso significa métricas rápidas e estáveis de pagamentos, jogos e complacência - dentro da SLA e orçamento.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Telegram
@Gamble_GC
Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.