1

今天在我的 Rails 应用程序上工作时,我注意到 paranoia gem 说应该更新索引以添加deleted_at IS NOT NULL作为索引创建的位置(github链接)。但是我突然想到,当我确实想要 with_deleted 时,倒置条件不会从索引中受益。

这让我想知道...

我知道这有点迟钝,因为答案显然是“这取决于你需要什么”,但我试图了解多列索引、单独索引和部分索引之间的区别,我的 Web 应用程序由 PostgreSQL 支持。

基本上,我有 2 个要查询的字段:p_id 和 deleted_at。大多数时候我都在查询WHERE p_id=1 AND deleted_at IS NOT NULL- 但有时我只查询WHERE p_id=1。很少,我会WHERE p_id=1 AND deleted_at=1/1/2017

那么,我是不是更好:

  1. 在 p_id 上有一个索引,在 deleted_at 上有一个单独的索引?
  2. 在 p_id 上有一个索引但添加 'where deleted_at IS NOT NULL'?
  3. 在 p_id 和 deleted_at 上有一个组合索引?

注意:也许我应该提到 p_id 当前是对 p.id 的外键引用。这提醒我,在 Postgres 中,外键是否有必要也有索引(或者它们是否获得了从外键约束派生的索引 - 我已经阅读了关于此的相互矛盾的答案)?

4

1 回答 1

3

答案取决于

  • 您使用这些查询的频率,以及允许它们运行多长时间
  • 如果查询速度足够重要以至于可以容忍缓慢的数据更改。

这三个子句的完美索引是:

  1. WHERE p_id=1 AND deleted_at IS NOT NULL

    CREATE INDEX ON mytable (p_id) WHERE deleted_at IS NOT NULL;
    
  2. WHERE p_id=1 AND deleted_at=1/1/2017

    CREATE INDEX ON mytable (p_id, deleted_at);
    
  3. WHERE p_id=1

    CREATE INDEX ON mytable (p_id);
    

为 2. 创建的索引也可以用于 3.,因此,如果您需要尽可能加快第二次查询的速度,并且稍微大一点的索引不会打扰您,请只为两个查询创建从 2. 开始的索引。

但是,来自 3. 的索引也会加快 2. 中的查询速度,只是不会尽可能快,所以如果您可以忍受 2. 中的查询性能稍差,并希望索引尽可能小且高效对于 3. 中的查询,只创建 3. 中的索引。

不会从 2. 和 3. 创建两个索引。你应该选择最适合你的。

1. 的情况不同,因为该索引只能用于第一个查询。仅当您想尽可能加快该查询时才创建该索引,并且表上的数据修改是否需要更长的时间并不重要,因为必须维护一个额外的索引。

在 1. 中创建索引的另一个指示是,如果只有一小部分行满足deleted_at IS NOT NULL. 如果不是,则 1. 中的索引与 3. 中的索引相比没有太大优势,您应该只创建后者。

在两列上有两个单独的索引可能不是最好的选择——它们只能与位图索引扫描结合使用,而且很可能 PostgreSQL 只选择使用其中一个索引(取决于分布,但可能是p_id),另一个没用。

于 2017-06-30T07:43:34.280 回答