我想从导入到 PostgreSQL 9.3.5 的 OpenStreetMap 数据库中检索给定名称的路线,操作系统是 Win7 64 位。为了具有一定的容错能力,我使用了 Postgres 的非重音扩展。
我的查询如下所示:
SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower(unaccent('unaccent','Weststrasse'))
查询计划:
Seq Scan on ways (cost=0.00..2958579.31 rows=122 width=465)
Filter: (lower((tags -> 'name'::text)) ~~ lower(unaccent('unaccent'::regdictionary, 'Weststrasse'::text)))
奇怪的是,这个查询对方法使用顺序扫描,尽管索引存在于lower(tags->'name')
:
CREATE INDEX ways_tags_name ON germany.ways (lower(tags -> 'name'));
一旦我从查询中删除非重音符号,Postgres 就会使用索引:
SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower('Weststrasse')
查询计划:
Index Scan using ways_tags_name on ways (cost=0.57..495.43 rows=122 width=465)
Index Cond: (lower((tags -> 'name'::text)) = 'weststrasse'::text)
Filter: (lower((tags -> 'name'::text)) ~~ 'weststrasse'::text)
为什么 unaccent 会阻止 Postgres 使用索引?在我看来,这是没有意义的,因为在执行实际查询之前,应该已经完全知道非重音符号(变音符号删除等)的结果。所以Postgres应该能够使用索引。使用unaccent时如何避免seq扫描?