索引可以定义在表的多个列上。例如,如果你有一个这样的表格
CREATE TABLE test2 ( major int, minor int, name varchar );
(比如说,你在数据库中保存你的 /dev
目录...) 并且你经常执行类似的查询
SELECT name FROM test2 WHERE major =constant
AND minor =constant
;
那么,在 major
和 minor
列上一起定义索引可能是合适的,例如:
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 节,以了解有关不同索引配置优缺点的一些讨论。
如果您在文档中发现任何错误,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表格 报告文档问题。