为什么 maxMerge() 给出的结果与 sumMerge() 的 max() 不同?

Why maxMerge() gives different results than max() of sumMerge()?

重点是获取每个周期的峰值(例如 5m 峰值)以获取累积值。因此需要对每个周期求和,然后可以在这些总和中找到峰值(最大值)。 (select max(v) from (select sum(v) from t group by a1, a2))


我有一个基地 table t.

数据插入t,考虑两个属性(时间t1和一些字符串a2)和一个数值

值会累加,因此需要将其相加得到一定时期内的总交易量。插入的行示例:

t1     | a2 | v
----------------
date1  | b  | 1
date2  | c  | 20

我正在使用 MV 来计算 sumState(),然后使用 sumMerge() 然后 max().

从中得到峰值

我只需要最大值,所以我想知道我可以直接使用 maxState()


所以这就是我现在所做的:我使用 MV 计算 5m 总和并从中读取 max()

CREATE TABLE IF NOT EXISTS sums_table ON CLUSTER '{cluster}' (
    t1              DateTime,
    a2              String,
    v               AggregateFunction(sum, UInt32)
)
ENGINE = ReplicatedAggregatingMergeTree(
    '...',
    '{replica}'
)
    PARTITION BY toDate(t1) 
    ORDER BY (a2, t1)
    PRIMARY KEY (a2);
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_a
    ON CLUSTER '{cluster}'
    TO sums_table
AS
SELECT toStartOfFiveMinute(t1) AS t1, a2,
    sumState(toUInt32(v)) AS v
FROM t
GROUP BY t1, a2

据此,我可以使用

读取 a2 的最大 5m 总和
SELECT
    a2,
    max(sum) AS max
FROM (
    SELECT
        t1,
        a2,
        sumMerge(v) AS sum
    FROM sums_table
    WHERE t1 BETWEEN :fromDateTime AND :toDateTime
    GROUP BY t1, a2
)
GROUP BY a2
ORDER BY max DESC

效果很好。


所以我想使用 maxStatemaxMerge():

来达到同样的效果
CREATE TABLE IF NOT EXISTS max_table ON CLUSTER '{cluster}' (
    t1              DateTime,
    a2              String,
    max_v           AggregateFunction(max, UInt32)
)
ENGINE = ReplicatedAggregatingMergeTree(
    '...',
    '{replica}'
)
    PARTITION BY toDate(t1) 
    ORDER BY (a2, t1)
    PRIMARY KEY (a2)
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_b
    ON CLUSTER '{cluster}'
    TO max_table
AS
SELECT
    t1,
    a2
    maxState(v) AS max_v
FROM (
    SELECT
        toStartOfFiveMinute(t1) AS t1,
        a2,
        toUInt32(sum(v)) AS v
    FROM t
    GROUP BY t1, a2
)
GROUP BY t1, a2

我想如果我得到每个时间 (t1) 和 a2 的最大值,然后 select 每个 a2 的最大值,我会得到每个 a2 的最大值,但我得到与上述总和的最大值相比,使用此查询的最大值完全不同。

SELECT
    a2,
    max(max) AS max
FROM (
    SELECT
        t1,
        a2,
        maxMerge(v) AS max
    FROM max_table
    WHERE t1 BETWEEN :fromDateTime AND :toDateTime
    GROUP BY t1, a2
) maxs_per_time_and_a2
GROUP BY a2

我做错了什么?我是不是看错了MV?是否可以将 maxStatemaxMerge 用于 2+ 个属性来计算较长时间段内的最大值,比方说年份?

SELECT
    t1,
    a2
    maxState(v) AS max_v
FROM (
    SELECT
        toStartOfFiveMinute(t1) AS t1,
        a2,
        toUInt32(sum(v)) AS v
    FROM t
    GROUP BY t1, a2
)
GROUP BY t1, a2

这是不正确的。而且不可能。 因为 MV 是插入触发器。它从不读取 REAL table t。 您正在从插入缓冲区中的行总和中获取最大值。

如果使用 v=10 插入 1 行。你会得到 max_v = 10。MatView 不“知道”之前的插入已经添加了一些行,它们的总和没有被考虑在内。