【问题标题】:Querying by range in your B-tree index's leading edge, PostgreSQL在 B-tree 索引的前沿 PostgreSQL 中按范围查询
【发布时间】:2013-06-10 05:23:18
【问题描述】:

如果您查询日期范围和其他内容,那么将日期列作为索引中的前沿是否是一件坏事?

我使用的是 PostgreSQL,但假设这适用于所有 B 树索引。

假设我查询了创建日期为 2013-01-02 或更晚且状态为“活动”的记录。我对 B 树索引如何组织日期很模糊,但这就是我的想象。如果索引打开(创建,状态),它的结构大致如下:

created       status
------------------------
2013-01-01    Active
2013-01-01    Inactive
2013-01-02    Active    <-- This record is selected
2013-01-02    Inactive
2013-01-03    Active    <-- This non-adjacent record is selected (SLOW)
2013-01-03    Inactive

如果索引开启(状态,创建):

status      created
------------------------
Active      2013-01-01
Active      2013-01-02    <-- This record is selected
Active      2013-01-03    <-- This adjacent record is selected (FAST)
Inactive    2013-01-01
Inactive    2013-01-02
Inactive    2013-01-03

所以在我看来,如果您使用日期作为前沿并查询这些日期的范围,那么您想要的记录会在索引中分散,导致性能下降。日期时间更糟。

【问题讨论】:

标签: oracle postgresql indexing b-tree


【解决方案1】:

我认为最好的方法是使用表达式索引。听起来您将主要运行以下查询:

select * from my_table where status='Active' and created_date > whatever

如果是这种情况,您可能会通过在创建日期创建索引并按状态过滤来获得最佳性能:

CREATE INDEX active_status_created_idx on my_table(created) WHERE status='Active'

这将导致可用于包括WHERE status='Active' 子句在内的任何查询的显着较小的索引。

见:

【讨论】:

    【解决方案2】:

    就我所读到的而言,您的假设都是正确的。您应该根据最常进行的查询类型来选择索引。

    如果您正在做很多where status = ? order by created limit 10order by status, created limit 10,那么(status, created) 上的索引通常是有序的。

    如果您经常使用where created = ? order by status limit 10order by created, status limit 10,那么您通常需要在(created, status) 上创建索引。

    请注意,Postgres 也允许对索引进行显式排序,例如(created, status desc)。文档对为什么有时需要这样做进行了冗长的讨论。 (我不记得具体在哪里,但我相信你已经发现它已经考虑到你如何表达你的问题了。)

    还要注意每种情况下的限制。 ordering 子句索引的使用取决于您要检索的行数。获取足够多的行,Postgres 可能更愿意完全忽略您精心创建的索引,而是通过其他方式检索前 n 种行。

    最后,请注意 Postgres 在管理单个列上的多个独立索引方面非常出色,尤其是在最近的版本中。事实上,手册中与索引相关的章节中有一个讨论正是讨论了这一点。

    如果您在(created)(status) 上有一个索引,那么当两者都具有足够的选择性时,它就会知道对诸如where status = ? and/or created = ? 之类的查询进行位图索引扫描。同样,它会知道只需将(created) 上的索引用于where status = ? order by created limit 10 等查询,并过滤掉status 没有正确值的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-02
      • 1970-01-01
      • 2020-12-14
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 2022-12-12
      相关资源
      最近更新 更多