web-dev-qa-db-ja.com

DATE_TRUNCによるインデックス付きグループソートを回避

GROUP BY関数がSortインデックスの一部であるtstampとして認識されないため、DATE_TRUNCix操作を回避する方法はありますか?その関数は、ixによって維持される順序に実際には影響しません。

CREATE INDEX ix ON tbl(col, tstamp, num)

  SELECT col,
         DATE_TRUNC('MONTH', tstamp AT TIME ZONE 'UTC') AS trunc,
         SUM(num)
    FROM tbl
   WHERE col IN (?, ?, ...)
     AND tstamp >= ?
     AND tstamp <  ?
GROUP BY col, trunc

DATE_TRUNCの精度パラメーターは動的であり、'DAY'または'YEAR'...の可能性もあります。そのため、バリエーションごとにインデックスを作成しないと、その関数にインデックスを付けることができません。

私が得る実行計画:

Finalize GroupAggregate
  Group Key: col, DATE_TRUNC('MONTH', tstamp AT TIME ZONE 'UTC')
  ->  Gather Merge
        Workers Planned: 2
        Workers Launched: 2
        ->  Partial GroupAggregate
              Group Key: col, DATE_TRUNC('MONTH', tstamp AT TIME ZONE 'UTC')
              ->  Sort
                    Sort Key: col, DATE_TRUNC('MONTH', tstamp AT TIME ZONE 'UTC')
                    Sort Method: external merge  Disk: ...kB
                    -> Parallel Index Only Scan using ix on tbl
                         Index Cond: ((col = ANY (...)) AND (tstamp >= ...) AND (tstamp < ...))
                         Heap Fetches: 0

実行計画は次のようになります。

GroupAggregate
  Group Key: col, DATE_TRUNC('MONTH', tstamp AT TIME ZONE 'UTC')
  ->  Index Only Scan using ix on tbl
        Index Cond: ((col = ANY (...)) AND (tstamp >= ...) AND (tstamp < ...))
        Heap Fetches: 0

DATE_TRUNCを使用しないと、それがわかります)

1
Nikola

PostgreSQLは、インデックススキャンによって返された行が正しくソートされるかどうかを認識していないため、クエリでのソートを回避する方法はありません。また、グループ集約ではソートされた入力が必要です。

唯一のチャンスは、ソートされた入力を必要としないハッシュ集計が得られるまでwork_memを増やすことです。

1
Laurenz Albe