PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

LEFT JOIN lento no CTE com intervalos de tempo


Correção primeiro :Suspeito de um bug na sua consulta:
 LEFT JOIN historical_ohlcv ohlcv ON ohlcv.time_open >= g.start_time
                                 AND ohlcv.time_close < g.end_time

Ao contrário da minha resposta referenciada, você entra em um intervalo de tempo :(time_open, time_close] . A maneira como você faz isso exclui linhas na tabela em que o intervalo cruza as fronteiras do bucket. Somente intervalos totalmente contidos em um único bucket contam. Eu não acho que isso é pretendido?

Uma correção simples seria decidir a associação do bucket com base em time_open (ou time_close ) sozinho. Se você quiser continuar trabalhando com ambos, você deve definir exatamente como lidar com intervalos sobrepostos com vários buckets.

Além disso, você está procurando por max(high) por bucket, que é de natureza diferente de count(*) na minha resposta referenciada.

E seus baldes são intervalos simples por hora?

Então podemos simplificar radicalmente. Trabalhando apenas com time_open :
SELECT date_trunc('hour', time_open) AS hour, max(high) AS max_high
FROM   historical_ohlcv
WHERE  exchange_symbol = 'BINANCE'
AND    symbol_id = 'ETHBTC'
AND    time_open >= now() - interval '5 months'  -- frame_start
AND    time_open <  now()                        -- frame_end
GROUP  BY 1
ORDER  BY 1;

Relacionado:
  • Reamostrar dados de série temporal

É difícil falar sobre otimização de desempenho adicional enquanto o básico não é claro. E precisaríamos de mais informações.

Estão WHERE variáveis ​​de condições?
Quantos valores distintos em exchange_symbol e symbol_id ?
Média tamanho da linha? O que você ganha:
SELECT avg(pg_column_size(t)) FROM historical_ohlcv t TABLESAMPLE SYSTEM (0.1);

A tabela é somente leitura?

Supondo que você sempre filtre em exchange_symbol e symbol_id e os valores são variáveis, sua tabela é somente leitura ou o autovacuum pode acompanhar a carga de gravação para que possamos esperar verificações somente de índice, é melhor ter um índice de várias colunas em (exchange_symbol, symbol_id, time_open, high DESC) para suportar esta consulta. Colunas de índice nesta ordem. Relacionado:
  • Índice e desempenho de várias colunas

Dependendo da distribuição de dados e outros detalhes, um LEFT JOIN LATERAL solução pode ser outra opção. Relacionado:
  • Como encontrar uma média de valores para intervalos de tempo no postgres
  • Otimize a consulta GROUP BY para recuperar o registro mais recente por usuário

Além de tudo isso, você EXPLAIN plano exibe alguns muito estimativas ruins :
  • https://explain.depesz.com/s/E5yI

Você está usando um atual versão do Postgres? Você pode ter que trabalhar na configuração do seu servidor - ou pelo menos definir metas de estatísticas mais altas em colunas relevantes e configurações de autovacuum mais agressivas para a tabela grande. Relacionado:
  • Evite que o PostgreSQL às vezes escolha um plano de consulta ruim
  • Autovacuum agressivo no PostgreSQL