sql >> Base de Datos >  >> RDS >> PostgreSQL

Slow LEFT JOIN en CTE con intervalos de tiempo

Corrección primero :Sospecho que hay un error en su consulta:

 LEFT JOIN historical_ohlcv ohlcv ON ohlcv.time_open >= g.start_time
                                 AND ohlcv.time_close < g.end_time

A diferencia de mi respuesta referenciada, te unes en un intervalo de tiempo :(time_open, time_close] . La forma en que lo hace excluye filas en la tabla donde el intervalo cruza los bordes del cubo. Solo cuentan los intervalos contenidos completamente en un solo depósito. ¿No creo que sea la intención?

Una solución simple sería decidir la membresía del depósito en función de time_open (o time_close ) solo. Si desea seguir trabajando con ambos, debe definir exactamente cómo lidiar con intervalos que se superponen con varios cubos.

Además, está buscando max(high) por cubo, que es diferente en naturaleza de count(*) en mi respuesta referenciada.

¿Y sus baldes son simples intervalos por hora?

Entonces podemos simplificar radicalmente. Trabajando solo con 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:

  • Volver a muestrear datos de series temporales

Es difícil hablar de una mayor optimización del rendimiento cuando los conceptos básicos no están claros. Y necesitaríamos más información.

Están WHERE variable de condiciones?
¿Cuántos valores distintos hay en exchange_symbol y symbol_id ?
Promedio tamaño de fila? ¿Qué obtienes por:

SELECT avg(pg_column_size(t)) FROM historical_ohlcv t TABLESAMPLE SYSTEM (0.1);

¿La tabla es de solo lectura?

Asumiendo que siempre filtras en exchange_symbol y symbol_id y los valores son variables, su tabla es de solo lectura o autovacuum puede mantenerse al día con la carga de escritura, por lo que podemos esperar escaneos de solo índice, lo mejor sería tener un índice de varias columnas en (exchange_symbol, symbol_id, time_open, high DESC) para apoyar esta consulta. Indexe las columnas en este orden. Relacionado:

  • Índice multicolumna y rendimiento

Dependiendo de la distribución de datos y otros detalles, un LEFT JOIN LATERAL solución podría ser otra opción. Relacionado:

  • Cómo encontrar un promedio de valores para intervalos de tiempo en postgres
  • Optimizar la consulta GROUP BY para recuperar el último registro por usuario

Aparte de todo eso, EXPLAIN el plan exhibe algo muy malas estimaciones :

  • https://explain.depesz.com/s/E5yI

¿Está utilizando un actual versión de postgres? Es posible que deba trabajar en la configuración de su servidor, o al menos establecer objetivos de estadísticas más altos en columnas relevantes y configuraciones de vacío automático más agresivas para la mesa grande. Relacionado:

  • Evite que PostgreSQL a veces elija un mal plan de consulta
  • Vacío automático agresivo en PostgreSQL