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