单次索引扫描只能利用那些在索引列上使用了该索引操作符类中操作符、并且彼此以AND连接的查询子句。例如,给定一个(a, b)上的索引,查询条件WHERE a = 5 AND b = 6可以使用该索引,而WHERE a = 5 OR b = 6这样的查询就不能直接使用该索引。
幸运的是,PostgreSQL能够组合多个索引(包括同一个索引的多次使用),以处理单次索引扫描无法实现的情况。系统可以在多个索引扫描之间形成AND和OR条件。例如,WHERE x = 42 OR x = 47 OR x = 53 OR x = 99这样的查询,可以拆分成对x上的一个索引进行四次独立扫描,每次扫描使用一个查询子句。然后将这些扫描的结果做 OR 运算以得到最终结果。另一个例子是,如果我们在x和y上分别有索引,那么WHERE x = 5 AND y = 6这样的查询,其一种可能实现方式就是分别用两个索引处理相应条件,然后将索引结果做 AND 运算,以确定结果行。
为了组合多个索引,系统会扫描每个所需索引,并在内存中准备一个位图,给出满足该索引条件的表行位置。然后按查询需要对这些位图进行 AND 和 OR 运算。最后,再访问并返回实际的表行。表行是按物理顺序访问的,因为位图就是这样布局的;这意味着原始索引中的任何排序都会丢失,所以如果查询带有ORDER BY子句,就需要单独的排序步骤。也正因为如此,再加上每多一次索引扫描都会增加额外时间,规划器有时会选择使用简单的单一索引扫描,即使还有其他本来也可以利用的索引。
除了最简单的应用之外,通常会有多种可能有用的索引组合,数据库开发者必须权衡决定提供哪些索引。有时多列索引最好,但有时创建独立索引并依赖索引组合功能会更合适。例如,如果你的工作负载包含一组查询:有时只涉及列x,有时只涉及列y,有时同时涉及两列,那么你可以选择分别在x和y上创建两个独立索引,并依赖索引组合来处理同时使用两列的查询。你也可以创建一个(x, y)上的多列索引。对于同时涉及两列的查询,这个索引通常会比索引组合更高效,但正如Section 11.3中所讨论的,它对于只涉及y的查询就没那么有用了。具体能有多大用处,取决于 B-树索引跳过扫描优化的效果;如果x的不同值不超过几百个,跳过扫描会让针对特定y值的搜索仍然具有相当不错的效率。再加上一个(x, y)上的多列索引和一个单独的y索引,也可能工作得相当好。对于只涉及x的查询,多列索引也可以使用,但它会比单独的x索引更大,因此更慢。最后一种选择是同时创建这三个索引,但这大概只有在该表被搜索的频率远高于被更新的频率,并且三类查询都很常见时才合理。如果其中一种查询远没有另外两种常见,那么你大概只需创建最适合常见查询类型的两个索引即可。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。