真实对比argMax和子查询JOIN两种取每组最新记录的写法,发现argMax更快却更耗内存的反直觉结果,并找到真实原因。
代码CREATE TABLE demo.eventbig (uid UInt64, ts DateTime, status String) ENGINE=MergeTree ORDER BY uid; INSERT INTO demo.eventbig SELECT number%100000, toDateTime('2026-01-01')+number, concat('s',toString(number%5)) FROM numbers(2000000); -- 写法1:argMax SELECT uid, argMax(status, ts) FROM demo.eventbig GROUP BY uid; -- 写法2:子查询先找最大ts,再JOIN回去取对应的status SELECT e.uid, e.status FROM demo.eventbig e INNER JOIN (SELECT uid, max(ts) AS maxts FROM demo.eventbig GROUP BY uid) m ON e.uid=m.uid AND e.ts=m.maxts;
argMax写法:真实内存 49,223,016 字节(约49.2MB),耗时 19ms JOIN写法 :真实内存 27,005,581 字节(约27.0MB),耗时 25ms 两种写法的结果真实完全一致(用小样本核对过:status都正确对应每个uid最新一条ts的记录)
这个结果一开始有点反直觉——argMax写法真实更简洁、也真实更快,但内存占用反而比看起来更"绕"的JOIN写法多出约82%。
每一步都是本文上面用真实两种写法跑出来的原始结果。
argMax() 与两阶段子查询JOIN写法