尽管索引,在postgresql geonames db中查询速度慢

时间:2016-08-30 05:58:34

标签: postgresql geonames

我将http://www.geonames.org/中的所有表格导入到我的本地postgresql 9.5.3.0数据库中,并用如下索引编写它:

create extension pg_trgm;
CREATE INDEX name_trgm_idx ON geoname USING GIN (name gin_trgm_ops);
CREATE INDEX fcode_trgm_idx ON geoname USING GIN (fcode gin_trgm_ops);
CREATE INDEX fclass_trgm_idx ON geoname USING GIN (fclass gin_trgm_ops);
CREATE INDEX alternatename_trgm_idx ON alternatename USING GIN (alternatename gin_trgm_ops);
CREATE INDEX isolanguage_trgm_idx ON alternatename USING GIN (isolanguage gin_trgm_ops);
CREATE INDEX alt_geoname_id_idx ON alternatename (geonameid)

现在我想查询不同语言的国家/地区名称,并使用这些替代名称交叉引用地理名称属性,如下所示:

select g.geonameid as geonameid ,a.alternatename as name,g.country as country, g.fcode as fcode
from geoname g,alternatename a
where
      a.isolanguage=LOWER('de')
      and a.alternatename ilike '%Sa%'
      and (a.ishistoric = FALSE OR a.ishistoric IS NULL)
      and (a.isshortname = TRUE OR a.isshortname IS NULL)
      and a.geonameid = g.geonameid
      and g.fclass='A'
      and g.fcode ='PCLI';

不幸的是,虽然这个查询在具有快速SSD的octacore机器上花费的时间长达13到15秒。 '解释分析详细'显示了这个:

Nested Loop  (cost=0.43..237138.04 rows=1 width=25) (actual time=1408.443..10878.115 rows=15 loops=1)
  Output: g.geonameid, a.alternatename, g.country, g.fcode
  ->  Seq Scan on public.alternatename a  (cost=0.00..233077.17 rows=481 width=18) (actual time=0.750..10862.089 rows=2179 loops=1)
        Output: a.alternatenameid, a.geonameid, a.isolanguage, a.alternatename, a.ispreferredname, a.isshortname, a.iscolloquial, a.ishistoric
        Filter: (((a.alternatename)::text ~~* '%Sa%'::text) AND ((a.isolanguage)::text = 'de'::text))
        Rows Removed by Filter: 10675099
  ->  Index Scan using pk_geonameid on public.geoname g  (cost=0.43..8.43 rows=1 width=11) (actual time=0.006..0.006 rows=0 loops=2179)
        Output: g.geonameid, g.name, g.asciiname, g.alternatenames, g.latitude, g.longitude, g.fclass, g.fcode, g.country, g.cc2, g.admin1, g.admin2, g.admin3, g.admin4, g.population, g.elevation, g.gtopo30, g.timezone, g.moddate
        Index Cond: (g.geonameid = a.geonameid)
        Filter: ((g.fclass = 'A'::bpchar) AND ((g.fcode)::text = 'PCLI'::text))
        Rows Removed by Filter: 1

对我而言似乎表明,不知何故,对481行(我认为相当低)进行了序列扫描,但仍需要很长时间。我目前无法理解这一点。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

如果您至少有3个字符,并且正在搜索%Sa%工作,%foo%,则三卦只会起作用。但是你的索引仍然不够好。根据动态使用多列或过滤索引的参数:

CREATE INDEX jkb1 ON geoname(fclass, fcode, geonameid, country);
CREATE INDEX jkb2 ON geoname(geonameid, country) WHERE fclass = 'A' AND fcode = 'PCLI';

另一张桌子相同:

CREATE INDEX jkb3 ON alternatename(geonameid, alternatename) WHERE (a.ishistoric = FALSE OR a.ishistoric IS NULL)
      AND (a.isshortname = TRUE OR a.isshortname IS NULL) AND isolanguage=LOWER('de')
相关问题