← 返回题目列表

PostgreSQL 扩展统计信息是什么?为什么多列相关性会影响执行计划?

困难 第 27 / 31 题 更新于 2026/07/30
PostgreSQL扩展统计执行计划

简化版

扩展统计信息用于帮助 PostgreSQL 理解多列之间的相关性、组合基数和函数依赖。普通统计通常按单列估算,如果两列强相关,优化器可能严重估错行数,进而选错 join 顺序或索引。

详细版

例如 country='CN'city='Beijing' 强相关。优化器如果把两个条件当独立事件,可能把结果估得过小或过大。

PostgreSQL 可以用:

CREATE STATISTICS st_user_country_city
ON country, city
FROM users;
ANALYZE users;

扩展统计能收集 ndistinctdependenciesmcv 等信息,帮助优化器更准确估算。它不是加速结构,本身不存数据访问路径,仍要配合索引和 ANALYZE

完整版教学

一、优化器为什么要估算行数

数据库执行 SQL 前要选计划:走哪个索引、先 join 哪张表、用 nested loop 还是 hash join。这些选择都依赖“估计会返回多少行”。

如果估算错了,计划就可能错。原本只返回 100 行的查询被估成 100 万行,优化器可能放弃索引;反过来,实际 100 万行被估成 100 行,也可能选择糟糕的 nested loop。

统计信息就是优化器的眼睛。

二、单列统计为什么不够

普通统计主要记录每列的分布,例如最常见值、直方图、不同值数量。但它默认列之间近似独立。

现实数据常常不独立。province='广东'city='广州' 强相关;is_deleted=falsedeleted_at IS NULL 也高度相关。

如果两个条件各自选择率都是 10%,独立假设会估成 1%。但真实相关时结果可能仍接近 10%,误差 10 倍。

三、扩展统计怎么创建

可以为多列创建统计对象:

CREATE STATISTICS st_orders_status_pay
ON status, pay_status
FROM orders;

ANALYZE orders;

创建统计对象后必须 ANALYZE,否则优化器没有新统计数据可用。统计对象只影响估算,不等于索引。

四、常见统计类型怎么理解

类型作用适合场景
ndistinct估算组合不同值数量多列 GROUP BY
dependencies识别函数依赖邮编决定城市
mcv多列最常见组合状态组合分布倾斜

例如订单状态和支付状态组合里,FINISHED + PAID 可能占 80%,FINISHED + UNPAID 几乎不可能。多列 MCV 能让优化器知道这种组合分布。

五、扩展统计和索引的关系

扩展统计不提供访问路径,所以它不能替代索引。它只是帮助优化器更准确判断某个路径划不划算。

索引:告诉数据库怎么找
统计:告诉优化器大概会找到多少

一个查询可能同时需要扩展统计和组合索引。统计让计划选得对,索引让执行跑得快。

六、常见误区与追问

  • 误区:扩展统计建完查询就一定更快。 它只改善估算,是否更快取决于计划是否因此变好。
  • 误区:扩展统计可以替代联合索引。 统计不是访问路径,不能直接减少扫描。
  • 误区:创建统计后不用维护。 数据分布变化后需要 ANALYZE 更新统计。
  • 追问:多列相关性会导致什么问题? 行数估算偏差,进而选错 join 顺序、join 算法或索引。
  • 追问:怎么判断估算错?EXPLAIN ANALYZE 里 estimated rows 和 actual rows 的差距。

七、加强记忆

记忆钩子:索引是路,统计是地图;多列相关性像地图上没画山路,路线规划就容易估错时间。

回答这题时把“优化器估算、独立假设、多列相关、CREATE STATISTICS、不能替代索引”串起来。它是 PostgreSQL 执行计划调优里很有含金量的中高级考点。