我想从导入 PostgreSQL 9.3.5 的 OpenStreetMap 数据库中检索具有给定名称的方式,操作系统是 Win7 64 位。为了有点容错性,我使用 Postgres 的 unaccent 扩展。
我的查询如下所示:
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'));
一旦我从查询中删除 unaccent,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 使用索引?在我看来,这没有意义,因为在执行实际查询之前,应该已经完全知道 unaccent 的结果(删除变音符号等)。所以 Postgres 应该可以使用索引。使用 unaccent 时如何避免 seq 扫描?