在Postgres中索引部分索引的条件

问题描述

我正试图推断Postgres partial indexes如何存储在Postgres中。假设我创建了这样的索引

CREATE INDEX orders_unbilled_index ON orders (order_nr)
WHERE billed is not true

为了快速运行类似查询

SELECT *
FROM orders
WHERE billed is not true AND order_nr > 1000000

Postgres显然在条件表达式order_nr定义的orders表子集上的billed is not true上存储了一个索引。但是,我有几个与此有关的问题:

  1. Postgres是否在billed is not true上内部存储另一个索引以快速查找与部分索引关联的行?
  2. 如果不是(1),那么如果我在billed is not true上创建了单独的索引,是否会使上面的查询运行更快? (假设一个大表,billed is true行少)

编辑:由于how boolean indexes are rarely used,基于docs的示例查询并不是最好的,但是请在任何条件表达式的上下文中考虑我的问题。

解决方法

b树索引可以认为是索引条目的有序列表,每个索引条目都有一个指向表中一行的指针。

在部分索引中,列表会更小:只有满足条件的行的索引条目。

如果您的WHERE子句中有索引条件,则PostgreSQL知道它可以使用索引,而不必检查索引条件,因为它会自动满足。

所以:

  1. 否,通过索引找到的任何行都将自动满足索引条件,因此使用索引足以确保满足要求。

  2. 否,将不会使用index on a boolean column,因为它不会比该部分索引便宜,并且该部分索引也可用于检查order_nr上的条件。

    实际上是另一回事:如果满足条件的行很少,则部分索引可以很好地用于仅在boolean条件下具有WHERE列的查询。

,

据我了解,Postgres只会建立一个索引,该索引只能用于查找billed为不正确的记录。也就是说,生成的B树将由order_nr进行索引,但仅在billed为假时才链接回原始表。

如果您继续阅读documentation,那么在引用之后,您会找到以下查询作为示例:

SELECT * FROM orders WHERE billed is not true AND amount > 5000.00;

Postgres可能 甚至选择使用您在上述查询中定义的索引的情况。它可以通过扫描整个索引来使用您的索引来满足此查询。如果尚未结算的订单数量相对较少,那么在order_nr上扫描索引可能比进行全表扫描更可取。

因此,您对问题#1的回答是:不,billed没有单独的索引,但是order_nr上的索引只能用于具有{{1} }设置为false。对于#2,是的,假设未开票的记录很少,可以使用billed上的第二个索引。但是,即使您当前的索引也可以原样使用。