array_agg默认包含null、不保证顺序、类型敏感且大结果易oom;应预过滤null、显式order by、谨慎处理类型转换,并限制单组数据量以防内存溢出。

ARRAY_AGG 会把 NULL 值也塞进数组里
默认行为下,ARRAY_AGG 不过滤 NULL,结果数组里可能出现 NULL 元素,这常导致后续 UNNEST 或应用层解析出错。
- 加
WHERE column_name IS NOT NULL预过滤(推荐,语义清晰) - 用
ARRAY_AGG(column_name) FILTER (WHERE column_name IS NOT NULL)(PostgreSQL 9.4+ 支持,更灵活) - 避免写
ARRAY_AGG(COALESCE(column_name, 'default'))——这会把NULL转成字符串,类型可能不一致
ORDER BY 必须显式声明,否则顺序不确定
ARRAY_AGG 不保证元素顺序,即使源表有索引或主键。没加 ORDER BY 的聚合结果在不同执行、不同 PostgreSQL 版本甚至同一查询多次运行中都可能变化。
- 正确写法:
ARRAY_AGG(value ORDER BY id) - 多字段排序也支持:
ARRAY_AGG(name ORDER BY priority DESC, created_at ASC) - 注意:
ORDER BY子句必须写在括号内,不能放在整个GROUP BY后面
聚合结果类型由输入列决定,跨类型要小心
如果聚合字段是混合类型(比如整数和字符串混用),或者用了表达式,PostgreSQL 会尝试隐式转换,失败就报错 ERROR: could not determine polymorphic type。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- 常见陷阱:
ARRAY_AGG(id || '_' || name)返回text[],但若id是bigint,某些旧版本可能报类型冲突 - 安全做法:显式类型转换,如
ARRAY_AGG((id::text || '_' || name)::text) - 聚合布尔值?
ARRAY_AGG(active)::boolean[]可以强制类型,但要注意空数组的类型推导可能失败
大结果集用 ARRAY_AGG 容易 OOM
当分组后某组数据量极大(比如上万行),ARRAY_AGG 会一次性把所有值加载进内存构建数组,可能触发 out of memory 或显著拖慢查询。
- 先用
LIMIT+ 子查询控制单组最大数量(如只取前 100 个) - 改用游标或应用层分页:先
GROUP BY拿到分组 key,再对每组单独查ARRAY_AGG - 考虑是否真需要完整数组——有时
STRING_AGG或 JSON 聚合(JSONB_AGG)更省内存且便于消费
数组长度超过几万时,就得怀疑是不是设计上该换思路了:要么加业务限制,要么拆开处理。直接硬扛容易在线上突然卡住。










