省略GROUP BY列时AggregatingMergeTree的聚合逻辑问询
背景
现有基于AggregatingMergeTree引擎的表app_events.events,通过物化视图从主表app_events.events_main同步数据:主表的event_timestamp字段被聚合为该表的min_time(类型为AggregateFunction(min, String)),且app_events.events的ORDER BY包含event_date、user_pseudo_id等字段。
核心问题
当GROUP BY子句中省略event_date列时,以下两个查询是否等价?
- 基于AggregatingMergeTree表的查询:
SELECT --event_date, --commented out this user_pseudo_id, event_params_ga_session_id, event_params_ga_session_number, minMerge(min_time) as min_time FROM app_events.events group by --event_date, --commented out this user_pseudo_id, event_params_ga_session_id, event_params_ga_session_number
- 基于主表的查询:
SELECT --event_date,--commented out this user_pseudo_id, event_params_ga_session_id, event_params_ga_session_number, min(event_timestamp) as min_time FROM app_events.events_main GROUP BY --event_date, --commented out this user_pseudo_id, event_params_ga_session_id, event_params_ga_session_number ;
另外,省略event_date后,使用minMerge的查询能否得到对应event_timestamp的最小聚合值?
回答
1. 两个查询完全等价
AggregatingMergeTree的核心是预计算聚合状态并存储,当你使用minMerge(min_time)时,ClickHouse会将所有分组下的min聚合状态合并,最终得到全局范围内以user_pseudo_id、event_params_ga_session_id、event_params_ga_session_number为分组的最小event_timestamp,和直接在主表上执行min(event_timestamp)并按相同字段分组的结果完全一致。
2. 能正确选择聚合状态,得到全局最小的event_timestamp
虽然app_events.events的ORDER BY包含event_date,但这仅影响数据的存储排序和合并逻辑,不会限制聚合状态的合并范围。当你在GROUP BY中省略event_date时,minMerge会跨所有event_date对应的聚合状态进行合并,最终计算出每个目标分组下的最小event_timestamp,结果和主表查询完全匹配。
内容的提问来源于stack exchange,提问作者Alexandr

