2024年9月26日: PostgreSQL 17发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:开发版本
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

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 节,以了解有关不同索引配置优缺点的一些讨论。

提交更正

如果您在文档中发现任何错误,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表格 报告文档问题。