即使所有部分都未在 where 子句中列出,PostgreSQL 是否会使用复合索引的部分内容?

Ale*_*yle 1 postgresql index index-tuning

我显然可以凭经验对此进行测试,但我发现在没有加载虚假数据的情况下EXPLAIN,Postgres 只是加载了包含表和扫描的完整内存页面。我也没有在文档中找到答案。

我的问题是,如果我在一个表上有一个索引,例如(colA, colB)一个包含where colA = 'something'Postgres的查询是否会使用这个索引,即使colB它不在查询中?假设不colA存在包含的索引。这个索引在查询执行中很有用是有道理的,但我很难确定地跟踪答案。

(Postgres v12.x)

J.D*_*.D. 5

是的,因为您示例中的复合索引也称为覆盖索引。在先前链接的文档中特别提到:

...人们有时通过将有效负载列写为普通索引列来覆盖索引,CREATE INDEX tab_x_y ON tab(x, y); 即使他们无意将 y 用作 WHERE 子句的一部分,也会这样写 。只要额外的列是尾随列,这就可以正常工作...

基本上,只要您的谓词的字段都是索引定义的顺序部分(从左到右),那么该索引就会覆盖并适用于该查询。

但是,您的示例的反向操作不起作用,因为索引不涵盖该场景。即WHERE colB = 'someValue'未被定义为索引的索引所覆盖,(colA, colB)因为索引定义中字段列表的顺序从字面上定义了用于对数据进行排序的底层B 树的结构。因此,首先将数据排序上colA,然后colB,使其无法直接搜索上colB(又名直接寻求colB,而仍然可以进行索引扫描来间接搜索上colB)没有谓语要搜索的colA第一位。

  • 它*可以*用于`colB='somevalue'`。它不会非常有效,因为它需要扫描整个索引而不仅仅是它的一部分,但如果表行比索引条目宽得多,这可能仍然比扫描表更有效。 (2认同)