クエリ:
SELECT
"places_place"."id"
FROM "places_place"
LEFT OUTER JOIN "units_unit" ON ("places_place"."id" = "units_unit"."place_id")
GROUP BY "places_place"."id"
HAVING SUM("units_unit"."quantity") >= 123
インデックス試行:
CREATE INDEX units_quantity_sum ON units_unit (SUM("units_unit"."quantity"));
-- ERROR: aggregate functions are not allowed in index expressions
基本的には、結果をテーブルの別の列に格納せずに、SUM
の結果にインデックスを付ける必要があります。これを行うにはどうすればインデックスを作成できますか(またはこのクエリを最適化するためのより良い方法があります)?
EXPLAIN ANALYZE
に10,000行を含むクエリのplaces_place
および25,000 in units_unit
:
HashAggregate (cost=2057.31..2157.33 rows=10002 width=4) (actual time=38.121..41.174 rows=7727 loops=1)
Group Key: places_place.id
Filter: (sum(units_unit.quantity) >= 5)
Rows Removed by Filter: 2275
-> Hash Right Join (cost=594.04..1932.22 rows=25018 width=6) (actual time=6.383..28.578 rows=26727 loops=1)
Hash Cond: (units_unit.place_id = places_place.id)
-> Seq Scan on units_unit (cost=0.00..994.18 rows=25018 width=6) (actual time=0.003..7.279 rows=25018 loops=1)
-> Hash (cost=469.02..469.02 rows=10002 width=4) (actual time=6.311..6.311 rows=10002 loops=1)
Buckets: 16384 Batches: 1 Memory Usage: 480kB
-> Seq Scan on places_place (cost=0.00..469.02 rows=10002 width=4) (actual time=0.007..3.560 rows=10002 loops=1)
Planning time: 0.584 ms
Execution time: 42.643 ms
2つの簡単なオプションがあります
MATERIALIZED VIEW
_を使用できますTRIGGER
を使用することもできます。これらの両方で、SUM()
をキャッシュできます。常に最新の変更が必要でない限り、_MATERIALIZED VIEW
_を使用します。
PostgreSQL 9.6でそのルートを進む前に、並列seqスキャンと集約を有効にすると、パフォーマンスが向上します。実際、これは 理想的な使用例 です。あなたがジャストこれを速くする必要がある場合は、設定を試してください _max_parallel_workers_per_gather
_