diff --git a/tests/cases/standalone/optimizer/reduce_aggregate_repartition.result b/tests/cases/standalone/optimizer/reduce_aggregate_repartition.result index eebf993717..675b650fcf 100644 --- a/tests/cases/standalone/optimizer/reduce_aggregate_repartition.result +++ b/tests/cases/standalone/optimizer/reduce_aggregate_repartition.result @@ -273,6 +273,68 @@ GROUP BY b, a; |_|_| Total rows: 4_| +-+-+-+ +-- Another grouped SQL reduction case to keep the rule coverage centered on SQL, +-- not just TQL/PromQL planning. +SELECT a, count(m) +FROM ( + SELECT a, b, c, min(val) AS m + FROM reduce_aggregate_repartition + GROUP BY a, b, c +) s +GROUP BY a +ORDER BY a; + ++---+------------+ +| a | count(s.m) | ++---+------------+ +| a | 3 | +| n | 3 | ++---+------------+ + +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (Hash.*) REDACTED +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +EXPLAIN ANALYZE +SELECT a, count(m) +FROM ( + SELECT a, b, c, min(val) AS m + FROM reduce_aggregate_repartition + GROUP BY a, b, c +) s +GROUP BY a; + ++-+-+-+ +| stage | node | plan_| ++-+-+-+ +| 0_| 0_|_AggregateExec: mode=SinglePartitioned, gby=[a@0 as a], aggr=[count(s.m)] REDACTED +|_|_|_CooperativeExec REDACTED +|_|_|_MergeScanExec: REDACTED +|_|_|_| +| 1_| 0_|_AggregateExec: mode=Final, gby=[a@0 as a], aggr=[__count_state(s.m)] REDACTED +|_|_|_CoalescePartitionsExec REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[a@0 as a], aggr=[__count_state(s.m)] REDACTED +|_|_|_ProjectionExec: expr=[a@0 as a, min(reduce_aggregate_repartition.val)@3 as m] REDACTED +|_|_|_AggregateExec: mode=FinalPartitioned, gby=[a@0 as a, b@1 as b, c@2 as c], aggr=[min(reduce_aggregate_repartition.val)] REDACTED +|_|_|_RepartitionExec: partitioning=REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[a@0 as a, b@1 as b, c@2 as c], aggr=[min(reduce_aggregate_repartition.val)] REDACTED +|_|_|_SeqScan: region=REDACTED, "partition_count":{"count":1, "mem_ranges":1, "files":0, "file_ranges":0} REDACTED +|_|_|_| +| 1_| 1_|_AggregateExec: mode=Final, gby=[a@0 as a], aggr=[__count_state(s.m)] REDACTED +|_|_|_CoalescePartitionsExec REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[a@0 as a], aggr=[__count_state(s.m)] REDACTED +|_|_|_ProjectionExec: expr=[a@0 as a, min(reduce_aggregate_repartition.val)@3 as m] REDACTED +|_|_|_AggregateExec: mode=FinalPartitioned, gby=[a@0 as a, b@1 as b, c@2 as c], aggr=[min(reduce_aggregate_repartition.val)] REDACTED +|_|_|_RepartitionExec: partitioning=REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[a@0 as a, b@1 as b, c@2 as c], aggr=[min(reduce_aggregate_repartition.val)] REDACTED +|_|_|_SeqScan: region=REDACTED, "partition_count":{"count":1, "mem_ranges":1, "files":0, "file_ranges":0} REDACTED +|_|_|_| +|_|_| Total rows: 2_| ++-+-+-+ + -- Zero-key reduction should rewrite SinglePartitioned to Single. SELECT sum(m) FROM ( @@ -407,3 +469,97 @@ DROP TABLE reduce_aggregate_repartition_non_subset; Affected Rows: 0 +CREATE TABLE reduce_aggregate_repartition_metric ( + ts TIMESTAMP(3) TIME INDEX, + job STRING, + instance STRING, + greptime_value DOUBLE, + PRIMARY KEY(job, instance), +); + +Affected Rows: 0 + +INSERT INTO reduce_aggregate_repartition_metric VALUES + (0, 'job1', 'instance1', 1), + (0, 'job1', 'instance2', 2), + (0, 'job2', 'instance1', 3), + (5000, 'job1', 'instance1', 4), + (5000, 'job1', 'instance2', 5), + (5000, 'job2', 'instance1', 6), + (10000, 'job1', 'instance1', 7), + (10000, 'job1', 'instance2', 8), + (10000, 'job2', 'instance1', 9); + +Affected Rows: 9 + +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +-- SQLNESS REPLACE (Hash.*) REDACTED +TQL ANALYZE (0, 10, '5s') +count(count(reduce_aggregate_repartition_metric) by (job)); + ++-+-+-+ +| stage | node | plan_| ++-+-+-+ +| 0_| 0_|_CooperativeExec REDACTED +|_|_|_MergeScanExec: REDACTED +|_|_|_| +| 1_| 0_|_SortExec: expr=[ts@0 ASC NULLS LAST], preserve_partitioning=[false] REDACTED +|_|_|_AggregateExec: mode=Final, gby=[ts@0 as ts], aggr=[count(count(reduce_aggregate_repartition_metric.greptime_value))] REDACTED +|_|_|_CoalescePartitionsExec REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[ts@0 as ts], aggr=[count(count(reduce_aggregate_repartition_metric.greptime_value))] REDACTED +|_|_|_ProjectionExec: expr=[ts@0 as ts] REDACTED +|_|_|_AggregateExec: mode=FinalPartitioned, gby=[ts@0 as ts, job@1 as job], aggr=[], ordering_mode=PartiallySorted([1]) REDACTED +|_|_|_SortExec: expr=[job@1 ASC], preserve_partitioning=[true] REDACTED +|_|_|_RepartitionExec: partitioning=REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[ts@0 as ts, job@1 as job], aggr=[], ordering_mode=PartiallySorted([1]) REDACTED +|_|_|_ProjectionExec: expr=[ts@0 as ts, job@1 as job] REDACTED +|_|_|_PromInstantManipulateExec: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] REDACTED +|_|_|_PromSeriesDivideExec: tags=["job", "instance"] REDACTED +|_|_|_SeriesScan: region=REDACTED, "partition_count":{"count":1, "mem_ranges":1, "files":0, "file_ranges":0}, "distribution":"PerSeries" REDACTED +|_|_|_| +|_|_| Total rows: 3_| ++-+-+-+ + +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +-- SQLNESS REPLACE (Hash.*) REDACTED +TQL ANALYZE (0, 10, '5s') +count(count(rate(reduce_aggregate_repartition_metric[5s])) by (job)); + ++-+-+-+ +| stage | node | plan_| ++-+-+-+ +| 0_| 0_|_CooperativeExec REDACTED +|_|_|_MergeScanExec: REDACTED +|_|_|_| +| 1_| 0_|_SortExec: expr=[ts@0 ASC NULLS LAST], preserve_partitioning=[false] REDACTED +|_|_|_AggregateExec: mode=Final, gby=[ts@0 as ts], aggr=[count(count(prom_rate(ts_range,greptime_value,ts,Int64(5000))))] REDACTED +|_|_|_CoalescePartitionsExec REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[ts@0 as ts], aggr=[count(count(prom_rate(ts_range,greptime_value,ts,Int64(5000))))] REDACTED +|_|_|_ProjectionExec: expr=[ts@1 as ts, count(prom_rate(ts_range,greptime_value,ts,Int64(5000)))@2 as count(prom_rate(ts_range,greptime_value,ts,Int64(5000)))] REDACTED +|_|_|_AggregateExec: mode=FinalPartitioned, gby=[job@0 as job, ts@1 as ts], aggr=[count(prom_rate(ts_range,greptime_value,ts,Int64(5000)))] REDACTED +|_|_|_RepartitionExec: partitioning=REDACTED +|_|_|_AggregateExec: mode=Partial, gby=[job@2 as job, ts@0 as ts], aggr=[count(prom_rate(ts_range,greptime_value,ts,Int64(5000)))] REDACTED +|_|_|_FilterExec: prom_rate(ts_range,greptime_value,ts,Int64(5000))@1 IS NOT NULL REDACTED +|_|_|_ProjectionExec: expr=[ts@0 as ts, prom_rate(ts_range@4, greptime_value@3, ts@0, 5000) as prom_rate(ts_range,greptime_value,ts,Int64(5000)), job@1 as job] REDACTED +|_|_|_PromRangeManipulateExec: req range=[0..10000], interval=[5000], eval range=[5000], time index=[ts] REDACTED +|_|_|_PromSeriesNormalizeExec: offset=[0], time index=[ts], filter NaN: [true] REDACTED +|_|_|_PromSeriesDivideExec: tags=["job", "instance"] REDACTED +|_|_|_SeriesScan: region=REDACTED, "partition_count":{"count":1, "mem_ranges":1, "files":0, "file_ranges":0}, "distribution":"PerSeries" REDACTED +|_|_|_| +|_|_| Total rows: 0_| ++-+-+-+ + +DROP TABLE reduce_aggregate_repartition_metric; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/optimizer/reduce_aggregate_repartition.sql b/tests/cases/standalone/optimizer/reduce_aggregate_repartition.sql index 1597c0a6cf..4c756ac703 100644 --- a/tests/cases/standalone/optimizer/reduce_aggregate_repartition.sql +++ b/tests/cases/standalone/optimizer/reduce_aggregate_repartition.sql @@ -58,6 +58,33 @@ FROM ( ) s GROUP BY b, a; +-- Another grouped SQL reduction case to keep the rule coverage centered on SQL, +-- not just TQL/PromQL planning. +SELECT a, count(m) +FROM ( + SELECT a, b, c, min(val) AS m + FROM reduce_aggregate_repartition + GROUP BY a, b, c +) s +GROUP BY a +ORDER BY a; + +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (Hash.*) REDACTED +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +EXPLAIN ANALYZE +SELECT a, count(m) +FROM ( + SELECT a, b, c, min(val) AS m + FROM reduce_aggregate_repartition + GROUP BY a, b, c +) s +GROUP BY a; + -- Zero-key reduction should rewrite SinglePartitioned to Single. SELECT sum(m) FROM ( @@ -120,3 +147,44 @@ FROM reduce_aggregate_repartition_non_subset GROUP BY b; DROP TABLE reduce_aggregate_repartition_non_subset; + +CREATE TABLE reduce_aggregate_repartition_metric ( + ts TIMESTAMP(3) TIME INDEX, + job STRING, + instance STRING, + greptime_value DOUBLE, + PRIMARY KEY(job, instance), +); + +INSERT INTO reduce_aggregate_repartition_metric VALUES + (0, 'job1', 'instance1', 1), + (0, 'job1', 'instance2', 2), + (0, 'job2', 'instance1', 3), + (5000, 'job1', 'instance1', 4), + (5000, 'job1', 'instance2', 5), + (5000, 'job2', 'instance1', 6), + (10000, 'job1', 'instance1', 7), + (10000, 'job1', 'instance2', 8), + (10000, 'job2', 'instance1', 9); + +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +-- SQLNESS REPLACE (Hash.*) REDACTED +TQL ANALYZE (0, 10, '5s') +count(count(reduce_aggregate_repartition_metric) by (job)); + +-- SQLNESS REPLACE (metrics.*) REDACTED +-- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED +-- SQLNESS REPLACE (-+) - +-- SQLNESS REPLACE (\s\s+) _ +-- SQLNESS REPLACE (peers.*) REDACTED +-- SQLNESS REPLACE region=\d+\(\d+,\s+\d+\) region=REDACTED +-- SQLNESS REPLACE (Hash.*) REDACTED +TQL ANALYZE (0, 10, '5s') +count(count(rate(reduce_aggregate_repartition_metric[5s])) by (job)); + +DROP TABLE reduce_aggregate_repartition_metric;