1. 统计信息收集
PostgreSQL 依赖于表和索引的统计信息来估算选择率。这些统计信息在以下情况下收集:
- ANALYZE 命令:手动运行 ANALYZE 命令来更新统计信息。
- 自动分析:PostgreSQL 会根据表的修改频率自动更新统计信息。
统计信息包括:
- 行数(tuples):表中总行数。
- 列的基数(distinct values):列中不同值的数量。
- 最小值和最大值:列中的最小和最大值。
- NULL 值的数量:列中 NULL 值的数量。
2. 选择率计算
选择率的计算通常基于以下公式:Selectivity=符合条件的行数\总行数
选择率的计算通常考虑以下因素:
- 单列条件:对于单列的条件,如等值查询(=),选择率可以通过基数和总行数来估算;对于范围查询(<, >, BETWEEN),则需要考虑值的分布。
- 多列条件:对于多列条件,例如 WHERE column1 = value1 AND column2 = value2,选择率的估算可能更复杂。优化器会考虑列之间的相关性(即列值之间的统计关系),并使用乘法法则来估算。
3. 复杂条件
对于复杂的查询条件(如AND、OR组合),PostgreSQL会使用以下策略:
- AND条件:选择率通常为各条件选择率的乘积。
- OR条件:选择率通常为各条件选择率的和,但需要考虑重叠部分。
4. 使用的函数
PostgreSQL使用一系列内置函数来帮助估算选择率,包括:
- eqsel:用于等值条件的选择率估算。
- ltsel、gtel:用于小于、大于条件的选择率估算。
- andselectivity、orselectivity:用于组合条件的选择率估算。
5. 使用直方图和其他统计信息
为了提高选择率估算的准确性,PostgreSQL 还使用直方图(histograms)和其他高级统计信息:
- 直方图:对于某些列,PostgreSQL 可以生成直方图,以更好地了解值的分布。这对于估算复杂条件(如范围查询)非常有用。
- 多维统计:PostgreSQL 允许使用多维统计信息来捕获多个列之间的相关性,帮助优化器更准确地估算选择率。
6. 估算过程中的调整
在估算过程中,PostgreSQL 可能会根据历史查询的执行情况进行调整。优化器会记录实际执行的查询计划的性能,以便在将来做出更好的选择。
7. 使用 GIN 和 GiST 索引
对于使用 GIN(Generalized Inverted Index)和 GiST(Generalized Search Tree)索引的查询,选择率的估算可能会更复杂,因为这些索引支持多值和复杂数据类型。优化器会根据索引的特性和历史使用情况来估算选择率。
8. 优化器
查询优化器(planner)使用这些选择率来选择最优的执行计划。选择率越低,通常意味着需要扫描的行数越少,从而影响执行计划中选择的索引和连接顺序。
总结
PostgreSQL 的选择率估算逻辑是查询优化的重要组成部分,涉及统计信息的收集、选择率的计算、直方图的使用以及历史执行情况的调整。通过这些机制,PostgreSQL 能够更有效地选择最佳的查询执行计划,从而提高查询性能。