diff --git a/tests/cases/standalone/common/promql/rate_fusion.result b/tests/cases/standalone/common/promql/rate_fusion.result new file mode 100644 index 00000000000..cbb43310542 --- /dev/null +++ b/tests/cases/standalone/common/promql/rate_fusion.result @@ -0,0 +1,98 @@ +CREATE TABLE rate_fusion ( + ts TIMESTAMP(3) TIME INDEX, + val DOUBLE, + dc STRING, + instance STRING, + PRIMARY KEY (dc, instance), +) WITH ('append_mode' = 'true'); + +Affected Rows: 0 + +INSERT INTO rate_fusion VALUES + (0, 0.0, 'shared', 'a'), + (60000, 60.0, 'shared', 'a'), + (120000, 120.0, 'shared', 'a'), + (180000, 180.0, 'shared', 'a'), + (240000, 240.0, 'shared', 'a'), + (300000, 300.0, 'shared', 'a'), + (0, 0.0, 'shared', 'b'), + (60000, 30.0, 'shared', 'b'), + (120000, 60.0, 'shared', 'b'), + (180000, 90.0, 'shared', 'b'), + (240000, 120.0, 'shared', 'b'), + (300000, 150.0, 'shared', 'b'), + (0, 10.0, 'other', 'c'), + (60000, 70.0, 'other', 'c'), + (120000, NULL, 'other', 'c'), + (180000, 100.0, 'other', 'c'), + (240000, 5.0, 'other', 'c'), + (300000, 65.0, 'other', 'c'), + (0, NULL, 'other', 'd'), + (60000, NULL, 'other', 'd'), + (120000, NULL, 'other', 'd'), + (180000, NULL, 'other', 'd'), + (240000, 42.0, 'other', 'd'), + (300000, NULL, 'other', 'd'); + +Affected Rows: 24 + +-- Two nonzero linear rates share one dc; the reset counter and sparse/all-NULL series +-- exercise reset handling, missing windows, and label aggregation in the other dc. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') sum by (dc) (rate(rate_fusion[2m])); + ++--------+---------------------+-----------------------------------------------+ +| dc | ts | sum(prom_rate(ts_range,val,ts,Int64(120000))) | ++--------+---------------------+-----------------------------------------------+ +| other | 1970-01-01T00:04:00 | 0.08333333333333333 | +| other | 1970-01-01T00:05:00 | 0.5416666666666666 | +| shared | 1970-01-01T00:02:00 | 1.5 | +| shared | 1970-01-01T00:03:00 | 1.5 | +| shared | 1970-01-01T00:04:00 | 1.5 | +| shared | 1970-01-01T00:05:00 | 1.5 | ++--------+---------------------+-----------------------------------------------+ + +-- Instant form of the same grouped aggregation at the final range step. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (300, 300, '60s') sum by (dc) (rate(rate_fusion[2m])); + ++--------+---------------------+-----------------------------------------------+ +| dc | ts | sum(prom_rate(ts_range,val,ts,Int64(120000))) | ++--------+---------------------+-----------------------------------------------+ +| other | 1970-01-01T00:05:00 | 0.5416666666666666 | +| shared | 1970-01-01T00:05:00 | 1.5 | ++--------+---------------------+-----------------------------------------------+ + +-- Offset and a different aggregator must not take the narrow fused path. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') sum by (dc) (rate(rate_fusion[2m] offset 1m)); + ++--------+---------------------+-----------------------------------------------+ +| dc | ts | sum(prom_rate(ts_range,val,ts,Int64(120000))) | ++--------+---------------------+-----------------------------------------------+ +| other | 1970-01-01T00:02:00 | 0.5833333333333334 | +| other | 1970-01-01T00:05:00 | 0.08333333333333333 | +| shared | 1970-01-01T00:02:00 | 0.75 | +| shared | 1970-01-01T00:03:00 | 1.5 | +| shared | 1970-01-01T00:04:00 | 1.5 | +| shared | 1970-01-01T00:05:00 | 1.5 | ++--------+---------------------+-----------------------------------------------+ + +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') min by (dc) (rate(rate_fusion[2m])); + ++--------+---------------------+-----------------------------------------------+ +| dc | ts | min(prom_rate(ts_range,val,ts,Int64(120000))) | ++--------+---------------------+-----------------------------------------------+ +| other | 1970-01-01T00:04:00 | 0.08333333333333333 | +| other | 1970-01-01T00:05:00 | 0.5416666666666666 | +| shared | 1970-01-01T00:02:00 | 0.5 | +| shared | 1970-01-01T00:03:00 | 0.5 | +| shared | 1970-01-01T00:04:00 | 0.5 | +| shared | 1970-01-01T00:05:00 | 0.5 | ++--------+---------------------+-----------------------------------------------+ + +DROP TABLE rate_fusion; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/promql/rate_fusion.sql b/tests/cases/standalone/common/promql/rate_fusion.sql new file mode 100644 index 00000000000..aff16140f94 --- /dev/null +++ b/tests/cases/standalone/common/promql/rate_fusion.sql @@ -0,0 +1,51 @@ +CREATE TABLE rate_fusion ( + ts TIMESTAMP(3) TIME INDEX, + val DOUBLE, + dc STRING, + instance STRING, + PRIMARY KEY (dc, instance), +) WITH ('append_mode' = 'true'); + +INSERT INTO rate_fusion VALUES + (0, 0.0, 'shared', 'a'), + (60000, 60.0, 'shared', 'a'), + (120000, 120.0, 'shared', 'a'), + (180000, 180.0, 'shared', 'a'), + (240000, 240.0, 'shared', 'a'), + (300000, 300.0, 'shared', 'a'), + (0, 0.0, 'shared', 'b'), + (60000, 30.0, 'shared', 'b'), + (120000, 60.0, 'shared', 'b'), + (180000, 90.0, 'shared', 'b'), + (240000, 120.0, 'shared', 'b'), + (300000, 150.0, 'shared', 'b'), + (0, 10.0, 'other', 'c'), + (60000, 70.0, 'other', 'c'), + (120000, NULL, 'other', 'c'), + (180000, 100.0, 'other', 'c'), + (240000, 5.0, 'other', 'c'), + (300000, 65.0, 'other', 'c'), + (0, NULL, 'other', 'd'), + (60000, NULL, 'other', 'd'), + (120000, NULL, 'other', 'd'), + (180000, NULL, 'other', 'd'), + (240000, 42.0, 'other', 'd'), + (300000, NULL, 'other', 'd'); + +-- Two nonzero linear rates share one dc; the reset counter and sparse/all-NULL series +-- exercise reset handling, missing windows, and label aggregation in the other dc. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') sum by (dc) (rate(rate_fusion[2m])); + +-- Instant form of the same grouped aggregation at the final range step. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (300, 300, '60s') sum by (dc) (rate(rate_fusion[2m])); + +-- Offset and a different aggregator must not take the narrow fused path. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') sum by (dc) (rate(rate_fusion[2m] offset 1m)); + +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (120, 300, '60s') min by (dc) (rate(rate_fusion[2m])); + +DROP TABLE rate_fusion; diff --git a/tests/perf/query_cases/promql_series_rate_fusion/README.md b/tests/perf/query_cases/promql_series_rate_fusion/README.md index 86d6d9fef93..0c153b2587e 100644 --- a/tests/perf/query_cases/promql_series_rate_fusion/README.md +++ b/tests/perf/query_cases/promql_series_rate_fusion/README.md @@ -9,7 +9,14 @@ instances × 512 samples = 2,097,152 rows, 16 `dc` values, 4 devices, and two fl non-overlapping SSTs of 1,048,576 rows each, 8,192-row groups, 15-second millisecond timestamps, primary key `(instance, dc, device)`, and deterministic wave values from 0 through 100. It uses the same data generator, not the -original 127-slope counter or an archived original input. +original 127-slope counter or an archived original input. In this fixed generator, +`wave_value` uses the global row ordinal modulo 1,024. Timestamp-major generation +with 4,096 series advances each series by 4,096 ordinals per sample, so each +series is constant over time and all rate results are zero. This preserves the +qualified input and still exercises range construction, but it is not sufficient +numeric-equivalence evidence; nonzero rates, resets, nulls and special values +must also pass the separate unit and SQLness cases. Do not replace this input +with a favorable distribution after seeing performance results. The range window is 1704069900–1704071715 seconds at 15-second steps (122 evaluations), fully covered by fixture timestamps from 1704067200 through