11.5. 合并多个索引

单个索引扫描只能使用查询子句,该查询子句将索引的列与其运算符类的运算符一起使用,并与AND联接。例如,给定(a, b)上的索引,像WHERE a = 5 AND b = 6这样的查询条件可以使用该索引,但是像WHERE a = 5 OR b = 6这样的查询不能直接使用该索引。

幸运的是,PostgreSQL 能够合并多个索引(包括对同一索引的多次使用)来处理无法通过单个索引扫描实现的情况。系统可以在几次索引扫描中形成ANDOR条件。例如,可以将类似WHERE x = 42 OR x = 47 OR x = 53 OR x = 99的查询分解为对x上的索引的四个单独的扫描,每个扫描都使用查询子句之一。然后将这些扫描的结果进行“或”运算以产生结果。另一个示例是,如果我们在xy上有单独的索引,则像WHERE x = 5 AND y = 6这样的查询的一种可能的实现方式是将每个索引与适当的查询子句一起使用,然后将索引结果与 AND 一起标识结果行。

为了合并多个索引,系统将扫描每个需要的索引,并在内存中准备一个* bitmap *,以提供报告为与该索引的条件匹配的表行的位置。然后根据查询需要对位图进行“与”或“或”运算。最后,访问并返回实际的表行。表行是按物理 Sequences 访问的,因为这是位图的布局方式。这意味着原始索引的任何排序都将丢失,因此如果查询具有ORDER BY子句,则需要一个单独的排序步骤。由于这个原因,并且由于每次附加索引扫描都会增加时间,因此计划程序有时会选择使用简单的索引扫描,即使也可以使用其他可用的索引。

在除最简单的应用程序之外的所有应用程序中,都有各种可能有用的索引组合,并且数据库开发人员必须权衡取舍才能确定要提供的索引。有时多列索引是最好的,但是有时最好创建单独的索引并依靠索引组合功能。例如,如果您的工作负载包含有时仅涉及x列,有时仅y列,有时仅涉及两列的查询混合,则您可以选择在xy上创建两个单独的索引,依靠索引组合来处理那些同时使用两列。您还可以在(x, y)上创建多列索引。对于同时涉及两个列的查询,此索引通常比索引组合更有效,但是如Section 11.3所述,对于仅涉及y的查询几乎没有用,因此它不应是唯一的索引。多列索引和y上的单独索引的组合将相当有效。对于仅涉及x的查询,可以使用多列索引,尽管它比单独的x上的索引更大,因此也较慢。最后一种选择是创建所有三个索引,但这仅在表搜索的频率比表更新的频率高得多并且所有三种查询类型都通用的情况下才是合理的。如果其中一种查询类型比其他查询类型少得多,那么您可能会选择只创建两个与通用类型最匹配的索引。