Skip to content

11.3. 多列索引#

可以针对表中的多列定义索引。例如,如果有一个如下所示的表

CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);

(比如说,您在数据库中保留了/dev目录...)并且您经常发出如下查询

SELECT name FROM test2 WHERE major = constant AND minor = constant;

那么,在列majorminor上一起定义索引可能是合适的,例如

CREATE INDEX test2_mm_idx ON test2 (major, minor);

目前,只有 B 树、GiST、GIN 和 BRIN 索引类型支持多键列索引。是否可以有多个键列与是否可以向索引中添加INCLUDE列无关。索引最多可以有 32 列,包括INCLUDE列。(在构建PostgreSQL时可以更改此限制;请参见文件pg_config_manual.h。)

多列 B 树索引可用于涉及索引列任意子集的查询条件,但当对前导(最左)列有约束时,索引效率最高。确切的规则是,前导列上的相等性约束,加上没有相等性约束的第一列上的任何不等性约束,将用于限制扫描的索引部分。这些列右侧列上的约束在索引中检查,因此它们可以节省对表的访问,但不会减少必须扫描的索引部分。例如,给定(a, b, c)上的索引和查询条件WHERE a = 5 AND b >= 42 AND c < 77,索引必须从a= 5 和b= 42 的第一个条目扫描到a= 5 的最后一个条目。具有c>= 77 的索引条目将被跳过,但仍然必须扫描它们。原则上,此索引可用于对b和/或c有约束而对a没有约束的查询 — 但必须扫描整个索引,因此在大多数情况下,计划程序更喜欢顺序表扫描而不是使用索引。

多列 GiST 索引可用于涉及索引列任意子集的查询条件。附加列上的条件限制索引返回的条目,但第一列上的条件是确定需要扫描多少索引的最重要条件。如果 GiST 索引的第一列只有几个不同的值,即使附加列中有许多不同的值,该索引也会相对无效。

多列 GIN 索引可用于涉及索引列任意子集的查询条件。与 B 树或 GiST 不同,无论查询条件使用哪个索引列,索引搜索效果都是相同的。

多列 BRIN 索引可用于涉及索引列任意子集的查询条件。与 GIN 类似,与 B 树或 GiST 不同,无论查询条件使用哪个索引列,索引搜索效果都是相同的。在单个表上拥有多个 BRIN 索引而不是一个多列 BRIN 索引的唯一原因是要有不同的pages_per_range存储参数。

当然,每个列都必须与适合索引类型的运算符一起使用;涉及其他运算符的子句将不被考虑。

应谨慎使用多列索引。在大多数情况下,单列索引就足够了,并且可以节省空间和时间。除非表的使用方式极其特殊,否则不太可能对包含三列以上的索引有所帮助。另请参阅第 11.5 节第 11.9 节,了解有关不同索引配置优点的一些讨论。