是否有数据库引擎可通过EXPLAIN等工具获取SQL聚合前的近似返回行数?
结论
目前不存在能在聚合执行前稳定给出你所需的聚合前实际返回行数高精度近似值的通用数据库功能,要拿到准确值的成本确实和执行改写后的count查询基本一致。
现有数据库的预估能力局限
你举的MySQL EXPLAIN的误差问题是所有数据库预估值的普遍情况:这类预估值都基于提前采样生成的统计信息(索引基数、直方图、表行数等),不是实时全量统计的结果,天生存在误差:
- 单表过滤条件数据分布倾斜时(比如你例子中
title>'u'的行数远低于平均分布的预期),误差会非常大 - 遇到多表JOIN、多层子查询、子查询内聚合这类复杂逻辑时,多步误差会叠加,最终预估值基本失去参考意义
少数数据库做了优化:比如PostgreSQL的EXPLAIN ANALYZE会给出实际执行后的准确行数,但本质是已经全量执行了一遍查询,不符合你「执行前获取」的要求;ClickHouse的EXPLAIN ESTIMATE、Spark的CBO优化器的预估精度比MySQL高,但复杂场景下误差依然可能超过100%,只能做粗略参考。
为什么没有低成本的完美解决方案
这个需求本质上确实受计算逻辑限制:
你要的聚合前行数,等于执行完所有过滤条件、子查询逻辑、JOIN逻辑后的中间结果行数,要拿到这个数值的准确值,就必须扫描所有符合条件的底层数据、执行关联逻辑,只是跳过了最终的聚合、排序、LIMIT步骤,成本和你改写的如下count查询完全一致:
SELECT COUNT(1) FROM sales JOIN ( SELECT id, person FROM sales2 WHERE country='US' GROUP BY person_id ) USING (id) WHERE sales.age > 20
如果可以接受一定误差,有两种折中方案可选:
- 采样估算:对底层表做1%~10%的随机采样,执行完整逻辑后把结果乘以采样比例,大部分场景下误差可以控制在20%以内,成本只有全量执行的几十分之一,Spark、Hive、ClickHouse都支持原生的表采样语法
- 预计算统计:如果你的查询模式固定,可以提前把常用过滤条件、关联逻辑的中间结果行数提前统计好存入专用的统计表,查询时直接读取,但是只能覆盖固定场景,查询条件变化后就失效
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

