11.3. 多字段索引

一个索引可以定义在一个表的多个字段上。比如下面这样的表(把/dev 目录保存在一个数据库里):

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

并且你经常发出下面这样的查询:

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

那么在字段majorminor 上联合定义一个索引是比较合适的做法,也就是:

CREATE INDEX test2_mm_idx ON test2 (major, minor);

目前,只有 B-tree , GiST和 GIN 支持多字段索引。缺省最多可以声明 32 个字段 (这个限制可以在编译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-tree 或 GiST,不管查询条件使用了哪些索引字段,索引的搜索效率是相同的。

当然,每个字段都必须和适合该索引类型的操作符一起使用;包含其它操作符的子句将不会被考虑。

使用多字段索引应该谨慎。在大多数情况下,在单字段上的索引就足够了,并且还节约时间和空间。 除非表的使用模式非常固定,否则超过三个字段的索引几乎没什么用处。 又见第 11.5 节获取有关不同索引设置的优缺点的讨论。