Postgres索引对原始SQL与ActiveRecord查询的影响大不相同

时间:2015-11-03 13:13:02

标签: ruby-on-rails postgresql ruby-on-rails-4 indexing postgresql-9.4

我有一个包含150k名称的表,并尝试向lower(name)添加索引以加快查找速度。该索引将原始SQL查询的速度提高了大约x100,但使用ActiveRecord执行的相同查询不会受到影响,如果不是有点慢。

这些是查询:

NamedEntity.where("lower(name) = ?", "John Doe".downcase).first

vs

conn.execute(
  %q{SELECT "named_entities".* FROM "named_entities" WHERE (lower(name) = 'john doe');}
)

我用

添加了索引
CREATE INDEX index_named_entities_on_lower_name ON named_entities USING btree (lower(name));

以下是比较所有案例的基准(每次执行50次):

no index,   AR:  6.999421
with index, AR:  7.264234
no index,   SQL: 5.569600
with index, SQL: 0.045464

查询计划与AR和SQL完全相同。

没有索引:

Seq Scan on named_entities  (cost=0.00..2854.31 rows=785 width=130)
  Filter: (lower((name)::text) = 'john doe'::text)

使用索引:

Bitmap Heap Scan on named_entities  (cost=9.30..982.51 rows=785 width=130)
  Recheck Cond: (lower((name)::text) = 'john doe'::text)
  ->  Bitmap Index Scan on index_named_entities_on_lower_name  (cost=0.00..9.26 rows=785 width=0)
        Index Cond: (lower((name)::text) = 'john doe'::text)

我不知道如何解释这个。 ActiveRecord添加的开销不应受索引的影响,因此对于AR和SQL,index和no index之间的差异应该是相同的,不是吗?

1 个答案:

答案 0 :(得分:0)

我通过在创建索引后添加ANALYZE named_entities;找到了解决问题的方法。这使得Postgres更新了各种事物的统计数据,因此它可以生成更好的查询计划。 (也发现Postgres docs太棒了。)

但仍然没有解释时差,因为explain表示SQL和AR查询都导致了相同的慢查询计划。