GROUP BY
関数がSort
インデックスの一部であるtstamp
として認識されないため、DATE_TRUNC
のix
操作を回避する方法はありますか?その関数は、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
を使用しないと、それがわかります)
PostgreSQLは、インデックススキャンによって返された行が正しくソートされるかどうかを認識していないため、クエリでのソートを回避する方法はありません。また、グループ集約ではソートされた入力が必要です。
唯一のチャンスは、ソートされた入力を必要としないハッシュ集計が得られるまでwork_mem
を増やすことです。