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

时间:2017-06-30 06:48:02

标签: ruby-on-rails postgresql indexing ruby-paranoia

今天在处理我的Rails应用程序时,我注意到偏执宝石表示应该更新索引以将deleted_at IS NOT NULL添加为索引创建的位置(github link)。但是我想到,当我想要with_deleted时,倒置的条件不会从索引中受益。

这让我想知道......

我知道这有些迟钝,因为答案很明显“这取决于你需要什么”但我试图了解多列索引与单独索引之间的差异与我支持的Web应用程序上的部分索引之间的差异通过PostgreSQL。

基本上,我有两个我要查询的字段: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上组合索引吗?
  4. 注意:也许我应该提一下p_id目前是p.id的外键引用。这让我想起,在Postgres中,外键还必须有索引(或者它们是否得到一个源自外键约束的索引 - 我已经阅读了相互矛盾的答案)?

1 个答案:

答案 0 :(得分:2)

答案取决于

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

这三个条款的完美索引是:

  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);
    
  4. 为2.创建的索引也可以用于3.,因此如果您需要尽可能加快第二个查询并且稍微大一点的索引不会打扰您,请仅从2创建索引。两个问题。

    然而,从3.开始的索引也会加速2中的查询,尽可能没有那么多,所以如果你能在2中查询稍差的性能,并希望索引尽可能小尽可能高效地进行3中的查询。仅在3中创建索引。

    创建两个索引。一个3。你应该选择最适合自己的东西。

    1.的情况不同,因为该索引只能用于第一个查询。仅在您希望尽可能加快查询速度时创建该索引,并且表上的数据修改需要更长时间并不重要,因为必须维护其他索引。

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

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