sql >> データベース >  >> RDS >> PostgreSQL

時間間隔のあるCTEでの低速左結合

    最初の正しさ :クエリにバグがあると思われます:

     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での積極的な自動バキューム



    1. PostgreSQL-データベースの名前を変更

    2. OracleデータベースのNLSパラメータのリスト

    3. SQLServerでセッションのANSI_NULLS設定を確認する方法

    4. varchar文字列を数値として注文する