PostgreSQL 11 引入的 INCLUDE 子句常被说成是为了支持索引覆盖扫描(index‑only scan),但覆盖索引在 9.2 之前的版本已经可以通过把所有查询列放入键列实现。INCLUDE 的核心价值在于:它允许在索引中额外存放列而不让这些列参与 B‑tree 的键排序和导航,从而在唯一约束、更新成本以及上层树结构上带来优势。
使用 INCLUDE 可以在保持索引大小不变的情况下,将不需要参与排序的列作为纯粹的负载存储,避免它们出现在分支页的键元组里,减小内部页面占用。对唯一约束而言,只有键列才会影响唯一性检查,INCLUDE 列不会破坏已有的唯一索引定义。
此外,INCLUDE 列不需要对应的操作符类,因而可以包含没有定义比较运算符的类型;在仅更新这些列时,PostgreSQL 还能利用自底向上的索引删除优化,提升写入性能。唯一限制是表达式不能作为 INCLUDE 列,若需要覆盖 ORDER BY,则必须把相应列放入键列。
关键区别
- 键列:参与 B‑tree 导航,出现在所有层级的分支页。
- INCLUDE 列:仅作为叶子页的额外负载,不参与键比较。
性能影响
- 对于只读查询,二者都能实现索引覆盖扫描。
- INCLUDE 索引在上层树更小,可能降低缓存压力。
- 但包含非键列会关闭 B‑tree 去重,导致在某些情况下索引体积略增。
在实际使用时,若仅需避免表访问而不改变唯一约束或排序需求,INCLUDE 是更轻量的选择;若查询需要排序或唯一约束涉及该列,则仍需将其放入键列。
#开发者 #工具 #PostgreSQL #INCLUDE #Btree #索引 @开发者工具库频道号
@DevToolboxHub
