我有一个包含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之间的差异应该是相同的,不是吗?
答案 0 :(得分:0)
我通过在创建索引后添加ANALYZE named_entities;
找到了解决问题的方法。这使得Postgres更新了各种事物的统计数据,因此它可以生成更好的查询计划。 (也发现Postgres docs太棒了。)
但仍然没有解释时差,因为explain
表示SQL和AR查询都导致了相同的慢查询计划。