PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Verlangsamen Sie LEFT JOIN auf CTE mit Zeitintervallen

Korrektheit zuerst :Ich vermute einen Fehler in Ihrer Abfrage:

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

Im Gegensatz zu meiner Antwort, auf die verwiesen wird, treten Sie in einem Zeitintervall Intervall bei :(time_open, time_close] . Auf diese Weise werden Zeilen in der Tabelle ausgeschlossen, in denen das Intervall Bucket-Grenzen überschreitet. Es zählen nur Intervalle, die vollständig in einem einzelnen Bucket enthalten sind. Ich glaube nicht, dass das beabsichtigt ist?

Eine einfache Lösung wäre, die Bucket-Mitgliedschaft basierend auf time_open zu entscheiden (oder time_close ) allein. Wenn Sie weiterhin mit beiden arbeiten möchten, müssen Sie genau definieren wie man mit Intervallen umgeht, die sich mit mehreren Buckets überschneiden.

Außerdem suchen Sie nach max(high) pro Bucket, was sich von Natur aus von count(*) unterscheidet in meiner referenzierten Antwort.

Und Ihre Buckets sind einfache Intervalle pro Stunde?

Dann können wir radikal vereinfachen. Arbeiten mit nur 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;

Verwandte:

  • Resample auf Zeitreihendaten

Es ist schwer, über weitere Leistungsoptimierung zu sprechen, solange die Grundlagen unklar sind. Und wir bräuchten mehr Informationen.

Sind WHERE conditions-Variable?
Wie viele unterschiedliche Werte in exchange_symbol und symbol_id ?
Durchschn. Zeilengröße? Was bekommen Sie für:

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

Ist die Tabelle schreibgeschützt?

Angenommen, Sie filtern immer nach exchange_symbol und symbol_id und Werte variabel sind, Ihre Tabelle schreibgeschützt ist oder die Selbstbereinigung mit der Schreiblast Schritt halten kann, sodass wir auf Index-Only-Scans hoffen können, sollten Sie am besten einen mehrspaltigen Index verwenden auf (exchange_symbol, symbol_id, time_open, high DESC) um diese Abfrage zu unterstützen. Indexspalten in dieser Reihenfolge. Verwandte:

  • Mehrspaltiger Index und Leistung

Je nach Datenverteilung und anderen Details ein LEFT JOIN LATERAL Lösung könnte eine andere Option sein. Verwandte:

  • So finden Sie einen Durchschnitt von Werten für Zeitintervalle in Postgres
  • Optimieren Sie die GROUP BY-Abfrage, um den neuesten Datensatz pro Benutzer abzurufen

Abgesehen von all dem EXPLAIN Sie Plan weist einige sehr auf schlechte Schätzungen :

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

Verwenden Sie einen Strom Version von Postgres? Möglicherweise müssen Sie an Ihrer Serverkonfiguration arbeiten - oder zumindest höhere Statistikziele für relevante Spalten und aggressivere Autovacuum-Einstellungen für die große Tabelle festlegen. Verwandte:

  • Halten Sie PostgreSQL davon ab, manchmal einen schlechten Abfrageplan zu wählen
  • Aggressive Selbstbereinigung auf PostgreSQL