跳转到主要内容

描述

State 组合器 可应用于 avg 函数,以生成 AggregateFunction(avg, T) 类型的中间状态,其中 T 是平均值的指定类型。

示例用法

在本示例中,我们将介绍如何结合使用 AggregateFunction 类型与 avgState 函数来聚合网站流量数据。 首先为网站流量数据创建源表:
CREATE TABLE raw_page_views
(
    page_id UInt32,
    page_name String,
    response_time_ms UInt32,  -- 页面响应时间(毫秒)
    viewed_at DateTime DEFAULT now()
)
ENGINE = MergeTree()
ORDER BY (page_id, viewed_at);
创建用于存储平均响应时间的聚合表。请注意,avg 无法使用 SimpleAggregateFunction 类型,因为它需要复杂状态 (包含求和值与计数值) 。因此,我们使用 AggregateFunction 类型:
CREATE TABLE page_performance
(
    page_id UInt32,
    page_name String,
    avg_response_time AggregateFunction(avg, UInt32)  -- 存储 avg 计算所需的状态
)
ENGINE = AggregatingMergeTree()
ORDER BY page_id;
创建一个增量materialized view,作为插入触发器处理新数据,并将中间状态数据存储到上面定义的目标表中:
CREATE MATERIALIZED VIEW page_performance_mv
TO page_performance
AS SELECT
    page_id,
    page_name,
    avgState(response_time_ms) AS avg_response_time  -- 使用 -State 组合器
FROM raw_page_views
GROUP BY page_id, page_name;
向源表插入一些初始数据,在磁盘上创建一个分片:
INSERT INTO raw_page_views (page_id, page_name, response_time_ms) VALUES
    (1, 'Homepage', 120),
    (1, 'Homepage', 135),
    (2, 'Products', 95),
    (2, 'Products', 105),
    (3, 'About', 80),
    (3, 'About', 90);
插入更多数据以在磁盘上创建第二个分片:
INSERT INTO raw_page_views (page_id, page_name, response_time_ms) VALUES
(1, 'Homepage', 150),
(2, 'Products', 110),
(3, 'About', 70),
(4, 'Contact', 60),
(4, 'Contact', 65);
检查目标表 page_performance
SELECT 
    page_id,
    page_name,
    avg_response_time,
    toTypeName(avg_response_time)
FROM page_performance
┌─page_id─┬─page_name─┬─avg_response_time─┬─toTypeName(avg_response_time)──┐
│       1 │ Homepage  │ �                 │ AggregateFunction(avg, UInt32) │
│       2 │ Products  │ �                 │ AggregateFunction(avg, UInt32) │
│       3 │ About     │ �                 │ AggregateFunction(avg, UInt32) │
│       1 │ Homepage  │ �                 │ AggregateFunction(avg, UInt32) │
│       2 │ Products  │ n                 │ AggregateFunction(avg, UInt32) │
│       3 │ About     │ F                 │ AggregateFunction(avg, UInt32) │
│       4 │ Contact   │ }                 │ AggregateFunction(avg, UInt32) │
└─────────┴───────────┴───────────────────┴────────────────────────────────┘
请注意,avg_response_time 列的类型为 AggregateFunction(avg, UInt32),存储的是中间状态信息。另外请注意,avg_response_time 的行数据对我们而言没有实际意义,显示的是诸如 \uFFFD, n, F, } 之类的乱码字符。这是终端尝试将二进制数据以文本形式呈现的结果。根本原因在于,AggregateFunction 类型以二进制格式存储其状态,该格式针对高效存储与计算进行了优化,而非为人类可读性而设计。这一二进制状态包含了计算平均值所需的全部信息。 要使用它,请使用 Merge 组合器:
SELECT
    page_id,
    page_name,
    avgMerge(avg_response_time) AS average_response_time_ms
FROM page_performance
GROUP BY page_id, page_name
ORDER BY page_id;
现在我们可以看到正确的平均值:
┌─page_id─┬─page_name─┬─average_response_time_ms─┐
│       1 │ Homepage  │                      135 │
│       2 │ Products  │       103.33333333333333 │
│       3 │ About     │                       80 │
│       4 │ Contact   │                     62.5 │
└─────────┴───────────┴──────────────────────────┘

另请参见

最后修改于 2026年6月10日