Hello,
I’m running into a performance issue where I’m trying to introduce a rollup into GROUP BY clause. I believe the query planner is missing an optimization when grouping by multiple terms.
Here’s an example that replicates the problem:
BEGIN;
CREATE TABLE limitation_demo (c1 integer, c2 integer, c3 integer, c4 integer);
INSERT INTO limitation_demo SELECT
(random() * 20)::integer,
(random() * 20)::integer,
(random() * 20)::integer,
(random() * 20)::integer
FROM generate_series(0,10000) AS foo;
CREATE INDEX idx1 ON limitation_demo (c1, c2, c3);
--Good
EXPLAIN SELECT * FROM (SELECT c1,c2,c3, sum(c4) FROM limitation_demo GROUP BY c1,c2,c3) AS foo WHERE c1 = 1 AND c2 = 5 ;
--Bad
EXPLAIN SELECT * FROM (SELECT c1,c2,c3, sum(c4) FROM limitation_demo GROUP BY c1, c2, ROLLUP(c3)) AS foo WHERE c1 = 1 AND c2 = 5;
ROLLBACK;
Here are the respective query plans:
QUERY PLAN
-----------------------------------------------------------------------------------
GroupAggregate (cost=0.29..8.32 rows=1 width=20)
Group Key: limitation_demo.c1, limitation_demo.c2, limitation_demo.c3
-> Index Scan using idx1 on limitation_demo (cost=0.29..8.30 rows=1 width=16)
Index Cond: ((c1 = 1) AND (c2 = 5))
(4 rows)
QUERY PLAN
----------------------------------------------------------------------------
HashAggregate (cost=255.02..360.03 rows=2 width=20)
Hash Key: limitation_demo.c1, limitation_demo.c2, limitation_demo.c3
Hash Key: limitation_demo.c1, limitation_demo.c2
Filter: ((limitation_demo.c1 = 1) AND (limitation_demo.c2 = 5))
-> Seq Scan on limitation_demo (cost=0.00..155.01 rows=10001 width=16)
(5 rows)
Despite being semantically equivalent, I believe, the latter plan with the rollup does not use the index. I believe what is happening is that the WHERE clause is getting pushed down into the inner query without the ROLLUP, but is not with the ROLLUP.
This is a simplified example. In my real-world use case, the inner query is a view, so I don’t have the option of moving the where clause.
Can y’all let me know if I should submit this somewhere else? Thanks!