11.3. 多列索引#
可以针对表中的多列定义索引。例如,如果有一个如下所示的表
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 节,了解有关不同索引配置优点的一些讨论。