【发布时间】:2015-03-06 12:42:43
【问题描述】:
我想从导入 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 扫描?
【问题讨论】:
-
列
tags的数据类型必须为hstore。这应该是问题所在,最好提供表定义(您从 psql 中的\d tbl获得的内容)。
标签: sql postgresql indexing openstreetmap unaccent