多列索引与单独索引与部分索引

Multi-column index vs seperate indexes vs partial indexes

今天在开发我的 Rails 应用程序时,我注意到偏执狂 gem 说应该更新索引以添加 deleted_at IS NOT NULL 作为创建索引的位置(github link).但我突然想到,当我想要 with_deleted 时,倒置条件不会从索引中受益。

这让我想知道...

我知道这有点迟钝,因为答案显然是 "it depends on what you need",但我想了解我的 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 中,外键是否也有索引(或者它们是否从外键约束中获得索引 - 我读过关于此的相互矛盾的答案)?

答案取决于

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

三个子句的完美索引是:

  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.的情况不同,因为该索引只能用于第一个查询。仅当您想尽可能加快该查询时才创建该索引,并且 table 上的数据修改是否花费更长时间并不重要,因为必须维护一个额外的索引。

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

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