最初の正しさ :クエリにバグがあると思われます:
LEFT JOIN historical_ohlcv ohlcv ON ohlcv.time_open >= g.start_time
AND ohlcv.time_close < g.end_time
私が参照した回答とは異なり、あなたは時間間隔で参加します :(time_open, time_close]
。これを行う方法では、間隔がバケットの境界を越えるテーブル内の行を除外します。単一のバケットカウントに完全に含まれる間隔のみ。それは意図されたものではないと思いますか?
簡単な修正は、time_open
に基づいてバケットメンバーシップを決定することです。 (またはtime_close
) 1人。両方で作業を続けたい場合は、正確に定義する必要があります 複数のバケットと重複する間隔を処理する方法。
また、max(high)
を探しています バケットごと。これは、count(*)
とは性質が異なります。 私の参照した答えで。
そして、あなたのバケツは1時間あたりの単純な間隔ですか?
そうすれば、根本的に単純化できます。 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;
関連:
- 時系列データのリサンプリング
基本は不明ですが、パフォーマンスの最適化について話すのは難しいです。そして、もっと情報が必要です。
WHERE
条件変数?
exchange_symbol
の個別の値の数 およびsymbol_id
?
平均行サイズ?何のために:
SELECT avg(pg_column_size(t)) FROM historical_ohlcv t TABLESAMPLE SYSTEM (0.1);
テーブルは読み取り専用ですか?
常にexchange_symbol
でフィルタリングすると仮定します およびsymbol_id
値は可変であり、テーブルは読み取り専用であるか、autovacuumが書き込み負荷に対応できるため、インデックスのみのスキャンを期待できます。複数列のインデックスが最適です。 (exchange_symbol, symbol_id, time_open, high DESC)
このクエリをサポートします。この順序で列にインデックスを付けます。関連:
- 複数列のインデックスとパフォーマンス
データの配布やその他の詳細に応じて、LEFT JOIN LATERAL
解決策は別のオプションかもしれません。関連:
- postgresで時間間隔の値の平均を見つける方法
- GROUP BYクエリを最適化して、ユーザーごとに最新のレコードを取得します
それとは別に、あなたはEXPLAIN
計画はいくつかの非常にを示します 悪い見積もり :
- https://explain.depesz.com/s/E5yI
現在を使用していますか Postgresのバージョン?サーバー構成で作業する必要がある場合があります。または、少なくとも関連する列に高い統計ターゲットを設定し、大きなテーブルに対してより積極的な自動真空設定を設定する必要があります。関連:
- PostgreSQLが時々悪いクエリプランを選択しないようにします
- PostgreSQLでの積極的な自動バキューム