-
Notifications
You must be signed in to change notification settings - Fork 870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: Bad plan produced when using CAGG name but good plan produced when using hypertable name! #6286
Comments
This could be related to #2841 somehow? |
Hi @jvanns, Could you pls share the definition of your cagg's materialized view (and if possible other details such as schema definition, caggs hierarchy definition etc) I've been trying to reproduce your use-case. I've noticed that the slower one pulls all the rows first then sorts them and runs aggregation, while the fast one just picks the first row from the I think I was able to reproduce the issue (see the example below). Pls let me know if it is similar to your situation. -- create and populate a hypertable
create table test (ts timestamp not null, device_id int, val float);
select create_hypertable('test', 'ts', chunk_time_interval=>'1 day'::interval);
insert into test
select
generate_series('2023-11-01', '2023-11-15', '1 minute'::interval) as ts,
(random() * 10)::int as device_id,
random() * 10 as val;
-- create an explicitly ORDERED cagg
create materialized view test_15m
with (
timescaledb.continuous,
timescaledb.materialized_only = true
) as
select
time_bucket('15 minute', "ts") AS ts,
min(val), max(val), avg(val)
from test
group by 1
order by 1;
-- a cagg without ORDER BY
create materialized view test_15m_unordered
with (
timescaledb.continuous,
timescaledb.materialized_only = true
) as
select
time_bucket('15 minute', "ts") AS ts,
min(val), max(val), avg(val)
from test
group by 1; And the query plans. The first one uses the matview with explicit # explain (analyze, costs off) select max(ts) from test_15m;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (actual time=1.358..1.362 rows=1 loops=1)
-> Result (actual time=0.042..1.157 rows=1345 loops=1)
-> Custom Scan (ChunkAppend) on _materialized_hypertable_2 (actual time=0.035..0.877 rows=1345 loops=1)
Order: _materialized_hypertable_2.ts
-> Index Only Scan Backward using _hyper_2_16_chunk__materialized_hypertable_2_ts_idx on _hyper_2_16_chunk (actual time=0.033..0.417 rows=768 loops=1)
Heap Fetches: 768
-> Index Only Scan Backward using _hyper_2_17_chunk__materialized_hypertable_2_ts_idx on _hyper_2_17_chunk (actual time=0.015..0.294 rows=577 loops=1)
Heap Fetches: 577
Planning Time: 1.410 ms
Execution Time: 1.439 ms
(10 rows) The second one just picks the first row from the top of the ordered by # explain (analyze, costs off) select max(ts) from test_15m_unordered;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Result (actual time=0.054..0.056 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Limit (actual time=0.047..0.049 rows=1 loops=1)
-> Custom Scan (ChunkAppend) on _materialized_hypertable_3 (actual time=0.045..0.046 rows=1 loops=1)
Order: _materialized_hypertable_3.ts DESC
-> Index Only Scan using _hyper_3_19_chunk__materialized_hypertable_3_ts_idx on _hyper_3_19_chunk (actual time=0.044..0.044 rows=1 loops=1)
Index Cond: (ts IS NOT NULL)
Heap Fetches: 1
-> Index Only Scan using _hyper_3_18_chunk__materialized_hypertable_3_ts_idx on _hyper_3_18_chunk (never executed)
Index Cond: (ts IS NOT NULL)
Heap Fetches: 0
Planning Time: 1.198 ms
Execution Time: 0.111 ms
(13 rows) |
Sure, with some obfuscation to hide any potential sensitive schema naming etc., our CAGG definition looks like this;
So you think its more to do with explicit ordering in the definition? Note that the peculiarity I reported seemed to be that if you queried via the CAGG VIEW name you get the 'bad' plan yet the exact same query against the underlying hypertable name, .e.g _materialized_hypertable_2 in your example above, produced the 'good' plan and executed in a far more acceptable time! Thanks for looking into it and reporting back. Glad to see there is at least a reproducible discrepancy of sorts. |
Just wanted to flag that this bug is still present and renders our CAGGs largely useless because they're impractical (result sets never returned in a reasonable time). I've managed to confirm the oddity does appear to arise from the use of ORDERing in the CAGG definition as @zilder has suspected and reproduced. I've attached two more 'bad' and 'better' plans that demonstrate the plan divergence simply by changing the CAGG name for the materialized hypertable name. Note that in tbe bad plan, for some reason, the ORDERing is applied for each column despite only ever querying on the timestamp (the 1st column in the ORDERing). The better plan is definitely more acceptable and expected. |
I can confirm that this indeed due to the use of an ORDER BY in the materialized view query definition. With it, queries always require a sort key using all those chosen fields. If removed, then the query is planned and executed more how you'd expect. |
Just noting that we've had to disable realtime aggregates, seemingly because of this issue 😢 |
What type of bug is this?
Performance issue
What subsystems and features are affected?
Continuous aggregate, Query planner
What happened?
Well, this is an odd one for sure and it's plagued be for weeks until I managed to narrow down where the problem lies. Although I cannot easily craft a full MRP for you, I can provide a straight-forward query and the resulting plans for you. The crux of the issue appears to be some sort of disconnect between CAGG name and hypertable name. I have 2x CAGGs - lets call them A and B. A sources from the main 'raw' hypertable, B sources from A thus creating a hierarchical CAGG setup. CAGG A buckets at 15m intervals, B at 30m intervals. The whole DB schema is created up-front via a .sql script and the CAGGs are explicitly created thus;
materialized only
NO DATA
chunk interval set to 12h on both
compression enabled
Here are the links to both the queries and respective plans;
https://explain.dalibo.com/plan/eag931806e5b6h82#plan
https://explain.dalibo.com/plan/0c8fbe46e424142e#plan
https://explain.dalibo.com/plan/54ec723bca45e7f7#plan
https://explain.dalibo.com/plan/a21542ffb46acf57#plan
Basically, using the underlying materialized hypertable name produces an expected good plan (executing in milliseconds) whereas using the CAGG name, we get a very odd 'bad' plan (executing in minutes). Whats more is this appears to effect other queries - the one provided is a simple way of reproducing it.
TimescaleDB version affected
2.11
PostgreSQL version used
15.3
What operating system did you use?
Centos 7.9
What installation method did you use?
Docker
What platform did you run on?
On prem/Self-hosted
Relevant log output and stack trace
How can we reproduce the bug?
Hopefully enough information is given above to start with. I'll try and provide an isolated MRP later.
The text was updated successfully, but these errors were encountered: