以下语句存在一个非常严重的性能问题,我无法自行修复。
给定情况
- 我有一个安装了 Postgis 1.4 的 postgres 8.4 数据库
- 我有一个大约 900 万个条目的地理空间表。该表有一个(postgis)几何列和一个 tsvector 列
- 我在几何上有一个 GIST 索引,在 vname 列上有一个 VNAME 索引
- 表是
ANALYZE
'd
我想to_tsquery
在这些几何的子集中执行文本搜索,这应该给我所有受影响的 id。
要搜索的区域会将 900 万个数据集限制为大约 100.000 个,并且ts_query
该区域内部的结果集很可能会给出 0..1000 个条目的输出。
问题
查询分析器决定他想先对 vname 进行位图索引扫描,然后聚合并在几何上放置一个过滤器(以及我在此语句中的其他条件)
查询分析器输出:
Aggregate (cost=12.35..12.62 rows=1 width=510) (actual time=5.616..5.616 rows=1 loops=1)
-> Bitmap Heap Scan on mxgeom g (cost=8.33..12.35 rows=1 width=510) (actual time=5.567..5.567 rows=0 loops=1)
Recheck Cond: (vname @@ '''hemer'' & ''hauptstrasse'':*'::tsquery)
Filter: (active AND (geom && '0107000020E6100000010000000103000000010000000B0000002AFFFF5FD15B1E404AE254774BA8494096FBFF3F4CC11E40F37563BAA9A74940490200206BEC1E40466F209648A949404DF6FF1F53311F400C9623C206B2494024EBFF1F4F711F404C87835954BD4940C00000B0E7CA1E4071551679E0BD4940AD02004038991E40D35CC68418BE49408EF9FF5F297C1E404F8CFFCB5BBB4940A600006015541E40FAE6468054B8494015040060A33E1E4032E568902DAE49402AFFFF5FD15B1E404AE254774BA84940'::geometry) AND (mandator_id = ANY ('{257,1}'::bigint[])))
-> Bitmap Index Scan on gis_vname_idx (cost=0.00..8.33 rows=1 width=0) (actual time=5.566..5.566 rows=0 loops=1)
Index Cond: (vname @@ '''hemer'' & ''hauptstrasse'':*'::tsquery)
这会导致大量 I/O - AFAIK 先限制几何形状,然后再进行 vname 搜索会更聪明。
尝试的解决方案
为了实现所需的行为,我试图
- 我将 geom @@
AREA
放入子选择中-> 没有更改执行计划 - 我用所需的区域子集创建了一个临时视图 -> 没有更改执行计划
- 我创建了一个所需区域的临时表 -> 创建需要 4~6 秒,这样就更糟了。
顺便说一句,很抱歉没有发布实际查询:我认为如果我这样做了,我的老板真的会生我的气,而且我正在寻找更多的理论指针来解决我的实际查询。请询问您是否需要进一步说明
编辑
width
Richard 有一个非常好的观点:您可以通过语句实现 Query Planner 的预期行为。坏事是这个临时表(或 CTE)弄乱了 vname 索引,因此在某些情况下使查询不返回任何内容。
我可以通过使用 动态创建一个新的 vname 来解决这个问题to_tsvector()
,但这(太)昂贵 - 每个查询大约 300 - 500 毫秒。
我的解决方案
我放弃了 vname 搜索并使用了一个简单的LIKE('%query_string%')
(10-20 毫秒/查询),但这仅在我给定的环境中速度很快。YMMV。