一个索引可以基于一个表中的多列来定义。例如,如果你有一个表格,其形式如下
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-Tree、GiST、GIN 和 BRIN 索引类型支持多键列索引。是否可以有多个键列与是否可以将 INCLUDE
列添加到索引无关。索引最多可以有 32 列,包含 INCLUDE
列。(此限制可以在构建 PostgreSQL 时更改,请参阅文件 pg_config_manual.h
。)
多列 B-Tree 索引可以用于包含索引的任意子集的列的查询条件,但当对前置(最左边的)列有约束时,索引的效率最高。具体规则是,前置列上的等式约束,加上没有相等约束的第一列上的任意不等式约束,将会用于限定要扫描的索引部分。这些列右侧的列的约束在索引中进行检查,因此它们可以节省对表本身的访问,但不会减少必须扫描的索引部分。例如,给定一个索引 (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 节,了解有关不同索引配置优点的一些讨论。