【问题标题】:Indexing the condition of a partial index in Postgres在 Postgres 中索引部分索引的条件
【发布时间】:2020-12-24 20:54:29
【问题描述】:

我试图推断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 上存储了一个索引,该索引建立在由条件表达式billed is not true 定义的orders 表的子集上。但是,我有几个与此相关的问题:

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

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

【问题讨论】:

    标签: postgresql indexing partial-index


    【解决方案1】:

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

    如果您继续阅读documentation,在您引用的内容之后,您会发现以下查询作为示例:

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

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

    因此,您的问题 #1 的答案是不,billed 没有单独的索引,而是 order_nr 上的索引只能用于将 billed 设置为 false 的记录。对于#2,是的,可以使用billed is not true 上的第二个索引,假设很少有记录未计费。但是,即使您当前的索引也可能会按原样使用。

    【讨论】:

      【解决方案2】:

      可以将 b-tree 索引视为索引条目的有序列表,每个条目都有一个指向表中一行的指针。

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

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

      所以:

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

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

        实际上是相反的:如果满足条件的行数足够少,部分索引可以很好地用于在WHERE 条件中只有boolean 列的查询。

      【讨论】:

        猜你喜欢
        • 2012-09-06
        • 2019-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 2023-03-06
        • 2010-11-15
        相关资源
        最近更新 更多