主键空值与重复需对比总行数、非空主键数、去重主键数:count()≠count(id)说明存在null主键,count()≠count(distinct id)说明存在重复主键;大表慎用count(distinct),改用group by id having count(*)>1;务必加where分区条件;sum校验需关注业务合理性,先过滤负值并设空值率阈值断言。

主键空值与重复的单次扫描检测
直接用 COUNT(*) 看不出主键是否脏,必须对比三个值:总行数、非空主键数、去重主键数。一次查清,避免多次全表扫描。
-
COUNT(*) != COUNT(id)→ 存在NULL主键 -
COUNT(*) != COUNT(DISTINCT id)→ 存在重复主键 - 大表慎用
COUNT(DISTINCT):Hive/Spark 中易 OOM,改用GROUP BY id HAVING COUNT(*) > 1分步排查 - 务必加
WHERE分区条件(如dt = '2026-06-23'),否则调度任务会拖垮集群
SUM 校验数值字段业务合理性
SUM 不报错,但结果反常就是最大预警信号。重点不是“能不能算”,而是“算出来合不合业务逻辑”。
- 先过滤负值:
COUNT(*) FILTER (WHERE amount 或 <code>SUM(CASE WHEN amount - 警惕隐式转换:MySQL 对字符串字段求和返回 0,PostgreSQL 直接报错
ERROR: function sum(text) does not exist,得提前用正则过滤:WHERE amount ~ '^[0-9.]+$' - 结合
AVG和STDDEV判断离散度——标准差远大于均值,大概率混入异常大额单或单位错误(比如“分”没转“元”)
把聚合结果转成断言脚本嵌入调度系统
人工看数字容易漏,真正落地要让数据库自己判断“是否异常”,返回空结果才算通过。
- 主键完整性断言:
HAVING COUNT(*) != COUNT(DISTINCT id) - 金额非负断言:
HAVING SUM(CASE WHEN amount 0 - 空值率阈值断言:
HAVING COUNT(*) * 0.05 (空手机号超 5% 就告警) - 这类语句必须带
WHERE分区裁剪,否则 Airflow 的SqlSensor会因超时失败
大数据量下聚合性能卡点在哪
不是函数本身慢,是它被迫扫太多数据。优化核心永远是“少扫”,而不是“快算”。
-
COUNT(*)在无索引大表上仍是全表扫描,别迷信“它最轻”——建(dt, id)复合索引并启用索引统计(PostgreSQL 的pg_class.reltuples)更稳 -
SUM或AVG涉及数值列时,覆盖索引要包含该列,否则回表开销可能抵消索引收益 - 日增千万级的表,别依赖实时聚合:用每日增量写入汇总表(如
daily_order_summary),SUM改查这张表,耗时从秒级降到毫秒级 -
GROUP BY分组维度越多,内存压力越大;审计场景优先按天+业务域两级分组,避免按用户 ID 这种高基数字段裸分组
实际跑起来才发现,最常被跳过的不是语法,而是分区裁剪和索引覆盖——写完脚本不加 WHERE dt = ...,或者以为建了 id 索引就能加速 SUM(amount),结果照样慢。











