Repository navigation
Closed
Labels
type: BugSomething isn't workingSomething isn't workingtype: Performancecloudberry runs slow on some particular querycloudberry runs slow on some particular query
Description
Cloudberry Database version
main
What happened
Optimizer could produce better plan to dedup based on cost.
What you think should happen instead
No response
How to reproduce
For the planner, we need to create better plan which uses HashAggregate to dedup columns.
For example,
ebi_dwh=# explain analyze WITH UniqueIDs AS (
SELECT DISTINCT gsp_id
FROM eft_com_call_statistic
)
SELECT COUNT(*)
FROM UniqueIDs;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=0.00..1419.47 rows=1 width=8) (actual time=2510.079..2510.081 rows=1 loops=1)
-> Gather Motion 4:1 (slice1; segments: 4) (cost=0.00..1419.47 rows=1 width=8) (actual time=1998.786..2510.054 rows=4 loops=1)
-> Partial Aggregate (cost=0.00..1419.47 rows=1 width=8) (actual time=1993.802..1993.803 rows=1 loops=1)
-> HashAggregate (cost=0.00..1419.47 rows=2315005 width=1) (actual time=1294.980..1855.013 rows=2339996 loops=1)
Group Key: gsp_id
-> Seq Scan on eft_com_call_statistic (cost=0.00..969.33 rows=2375680 width=37) (actual time=0.343..339.551 rows=2377251 loops=1)
Planning Time: 5.357 ms
(slice0) Executor memory: 98354K bytes.
(slice1) Executor memory: 244665K bytes avg x 4x(0) workers, 244755K bytes max (seg2). Work_mem: 286737K bytes max.
Memory used: 2097152kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution Time: 2584.618 ms
(12 rows)
This plan uses HashAggregate to perform gsp_id deduplication, while
ebi_dwh=# explain analyze select count(distinct gsp_id) from eft_com_call_statistic;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=0.00..1142.67 rows=1 width=8) (actual time=10573.416..10573.418 rows=1 loops=1)
-> Gather Motion 4:1 (slice1; segments: 4) (cost=0.00..1142.67 rows=1 width=8) (actual time=10205.645..10573.387 rows=4 loops=1)
-> Partial Aggregate (cost=0.00..1142.67 rows=1 width=8) (actual time=10437.005..10437.007 rows=1 loops=1)
-> Seq Scan on eft_com_call_statistic (cost=0.00..969.33 rows=2375680 width=37) (actual time=0.269..548.673 rows=2377251 loops=1)
Planning Time: 4.608 ms
(slice0) Executor memory: 37K bytes.
(slice1) Executor memory: 148480K bytes avg x 4x(0) workers, 148579K bytes max (seg2).
Memory used: 2097152kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution Time: 10573.853 ms
(10 rows)
It seems the cost estimation is no accurate.
Operating System
No specific
Anything else
No
Are you willing to submit PR?
- Yes, I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct.
Metadata
Metadata
Labels
type: BugSomething isn't workingSomething isn't workingtype: Performancecloudberry runs slow on some particular querycloudberry runs slow on some particular query
Activity
my-ship-it commentedon Oct 11, 2024
For Postgres planner, in function
add_single_dqa_hash_agg_path, the code doesn't match the comments.We need to investigate that:
avamingli commentedon Oct 15, 2024
Do we have reproduce SQL steps?
jianlirong commentedon Oct 15, 2024
Please check the description of this issue above. You can create a very simple table, and insert some data. Then, you can use the above SQL statements to reproduce this issue.
avamingli commentedon Oct 15, 2024
Hi all, I try to reproduce with some data, but got the opposite result: with_cte is slower than normal agg.
Here is my case, I use AO table to make sure that there is no buffer cache when comparing results each time.
Normal AGG
Use a CTE SQL:
avamingli commentedon Oct 15, 2024
Same for ORCA:
Use CTE SQL:
jianlirong commentedon Oct 15, 2024
I think you had reproduced the problem: we generated two different plans for those two SQL statements which are functionally equivalent. One uses the GroupAggregate node to perform deduplication, while other uses the HashAggregate to perform deduplication.
You can easily create a case where HashAggregate for deduplication is more efficient than GroupAggregate.
Based on the table you created, try this:
And then, run the tests again.
avamingli commentedon Oct 15, 2024
Got it, now this case, CTE works better.
avamingli commentedon Oct 15, 2024
I debug this for a while:
For CTE SQL, the HashAgg on SeqScan came from CTE path, and planner do a count agg on the CTE subquery, so the plan has an additional DEDUP HashAgg node, and it must be that one.
For SQL:
select count(distinct id) from ao;I found we already have the codes to add an additional DEDUP HashAgg path in PG planner.
Yes, there was a path like that, HashAgg on Seqscan to DEDUP, but it's dropped due to cost compared to a normal two-stage aggregation path by planner.
Either is correct for :
select count(distinct id) from ao;.The cost of HashAggregate to dedup may need to be adjusted.
my-ship-it commentedon Oct 16, 2024
Yes, in fact, dedup + count is much faster than count(distinct) in some cases. We need to adjust cost estimation very carefully.
avamingli commentedon Oct 16, 2024
Correction: after some debug, I found there is no such a path,
the DEDUP HashAgg currently we have is much like a one-phase agg:
That's not we expected, it gather all live tuples to do agg on master.
We need to generate a plan to handle DISTINCT as the CTE plan does and let it win according to user's cases.
That is much like 3-phase AGG in GPDB, and I'm working on it.
3 remaining items
my-ship-it commentedon Oct 17, 2024
Close due to already fixed.
aeschbacherEUF commentedon Nov 7, 2024
Hi Team,
Eddie provided us with a test RPM package containing the single fix for issue #676 (already cherry-picked and built into v1.6.0):
Implement 3-phase aggregation with DEDUP HashAgg for DISTINCT. #676
We conducted some real-data testing, hoping for better performance with optimizer=on (needed for our typical workload) and gp_eager_distinct_dedup=on. Unfortunately, the PostgreSQL optimizer still outperforms ORCA by a factor of two. We've attached the EXPLAIN ANALYZE output for your reference.
fix_659_distinct_cdb161.txt
Best regards,
Andreas
edespino commentedon Nov 7, 2024
I am reopening this so there can be a discussion in response to aeschbacherEUF comment.
aeschbacherEUF commentedon Nov 7, 2024
`set gp_eager_distinct_dedup = on;
set optimizer = on;
set optimizer_enable_multiple_distinct_aggs = off;
explain (analyze, verbose, costs, timing, buffers) select count(distinct gsp_id) from eft_com_call_statistic;`
QUERY PLAN
Finalize Aggregate (cost=0.00..1252.01 rows=1 width=8) (actual time=9613.853..9613.854 rows=1 loops=1)
Output: count(DISTINCT gsp_id)
-> Gather Motion 2:1 (slice1; segments: 2) (cost=0.00..1252.01 rows=1 width=8) (actual time=9408.391..9613.841 rows=2 loops=1)
Output: (PARTIAL count(DISTINCT gsp_id))
-> Partial Aggregate (cost=0.00..1252.01 rows=1 width=8) (actual time=9612.691..9612.693 rows=1 loops=1)
Output: PARTIAL count(DISTINCT gsp_id)
-> Seq Scan on ebi_data.eft_com_call_statistic (cost=0.00..1103.70 rows=3958250 width=19) (actual time=0.222..940.759 rows=3958373 loops=1)
Output: gsp_id
Settings: effective_cache_size = '8GB', optimizer = 'on'
Planning:
Buffers: shared hit=2
Planning Time: 5.153 ms
(slice0) Executor memory: 37K bytes.
(slice1) Executor memory: 130705K bytes avg x 2x(0) workers, 130705K bytes max (seg0).
Memory used: 131072kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution Time: 9614.687 ms
(17 rows)
Time: 9620,598 ms (00:09,621)
==================================================================================
`set gp_eager_distinct_dedup = on;
set optimizer = on;
set optimizer_enable_multiple_distinct_aggs = off;
explain (analyze, verbose, costs, timing, buffers)
WITH cte_gsp_counts AS (
SELECT DISTINCT gsp_id
FROM eft_com_call_statistic
)
SELECT COUNT(*)
FROM cte_gsp_counts;
`
QUERY PLAN
Finalize Aggregate (cost=0.00..1721.24 rows=1 width=8) (actual time=3438.953..3438.955 rows=1 loops=1)
Output: count()
-> Gather Motion 2:1 (slice1; segments: 2) (cost=0.00..1721.24 rows=1 width=8) (actual time=3423.515..3438.943 rows=2 loops=1)
Output: (PARTIAL count())
-> Partial Aggregate (cost=0.00..1721.24 rows=1 width=8) (actual time=3433.644..3433.645 rows=1 loops=1)
Output: PARTIAL count()
-> HashAggregate (cost=0.00..1721.24 rows=3958250 width=1) (actual time=1993.244..3310.569 rows=3958365 loops=1)
Output: gsp_id
Group Key: eft_com_call_statistic.gsp_id
Planned Partitions: 4
work_mem: 262433kB Segments: 2 Max: 131217kB (segment 0) Workfile: (2 spilling)
-> Seq Scan on ebi_data.eft_com_call_statistic (cost=0.00..1103.70 rows=3958250 width=19) (actual time=0.376..915.290 rows=3958373 loops=1)
Output: gsp_id
Settings: effective_cache_size = '8GB', optimizer = 'on'
Planning:
Buffers: shared hit=6
Planning Time: 4.713 ms
(slice0) Executor memory: 24626K bytes.
(slice1) Executor memory: 123097K bytes avg x 2x(0) workers, 123117K bytes max (seg0). Work_mem: 131217K bytes max.
Memory used: 131072kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution Time: 3448.772 ms
(22 rows)
Time: 3454,306 ms (00:03,454)
my-ship-it commentedon Nov 7, 2024
Hi @aeschbacherEUF, please try it with optimizer = off;
aeschbacherEUF commentedon Nov 7, 2024
that will speed the count distinct but for a lot of other queries we would need to have optimizer set to on
my-ship-it commentedon Nov 11, 2024
Yeah. We also need to enable it for ORCA.
my-ship-it commentedon Nov 15, 2024
We found ORCA already have the path. Maybe need to adjust the cost.
jiaqizho commentedon Nov 18, 2024
my test case is
and the ORCA memo is:
then the lowest cost path is:
let us see the group 7(only one path to do the seq scan):
then below path can add
group 7, expr 1as its child:The parent path of path abc
group 9,expr 1the same asgroup 7, expr 1, and onlyCPhysicalMotionHashDistribute/CPhysicalMotionRandom/Sortpath exists.So i guess we need add a path in the ORCA...
my-ship-it commentedon Nov 19, 2024
Good analysis, yes, I think so...
jiaqizho commentedon Dec 12, 2024
Hi , @aeschbacherEUF
Would like try apply the #776 ?
here is my output
ORCA will force use the 3-stage agg...