我有一个区域表,每个区域都有一个表示其多边形在地图上的geom值。还有另一个房屋表,其中每个房子都有一个在地图上表示其点的geom值。
这两个geom列均使用gist进行索引,并且区域表的名称列也进行了索引。区域表有8k+条记录,而房屋表有300k+条记录。
现在我的任务是找出名为“FOO”的区域内的所有房屋。
查询#1:
这两个geom列均使用gist进行索引,并且区域表的名称列也进行了索引。区域表有8k+条记录,而房屋表有300k+条记录。
现在我的任务是找出名为“FOO”的区域内的所有房屋。
查询#1:
SELECT * FROM houses WHERE ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom);
查询计划结果:
Seq Scan on houses (cost=8.29..86327.26 rows=102365 width=136)
Filter: st_intersects($0, geom)
InitPlan 1 (returns $0)
-> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32)
Index Cond: ((suburb_name)::text = 'FOO'::text)
运行查询花费了约3.5秒,返回了486条记录。
查询 #2:(在ST_INTERSECTS函数前加下划线,以显式要求不使用索引)
SELECT * FROM houses WHERE _ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom);
查询计划结果:(与查询#1完全相同)
Seq Scan on houses (cost=8.29..86327.26 rows=102365 width=136)
Filter: st_intersects($0, geom)
InitPlan 1 (returns $0)
-> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32)
Index Cond: ((suburb_name)::text = 'FOO'::text)
运行查询耗时约1.7秒,返回486条记录。
查询#3: (在ST_Intersects函数前使用&&操作符添加边界框重叠检查)
SELECT * FROM houses WHERE (geom && (SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO')) AND ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom);
查询计划结果:
Bitmap Heap Scan on houses (cost=21.11..146.81 rows=10 width=136)
Recheck Cond: (geom && $0)
Filter: st_intersects($1, geom)
InitPlan 1 (returns $0)
-> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32)
Index Cond: ((suburb_name)::text = 'FOO'::text)
InitPlan 2 (returns $1)
-> Index Scan using suburbs_suburb_name on suburbs suburbs_1 (cost=0.28..8.29 rows=1 width=32)
Index Cond: ((suburb_name)::text = 'FOO'::text)
-> Bitmap Index Scan on houses_geom_gist (cost=0.00..4.51 rows=31 width=0)
Index Cond: (geom && $0)
运行查询花费了0.15秒,返回了486条记录。
显然只有查询#3从空间索引中获得了好处,这显著提高了性能。 然而,语法很丑陋,并且在某种程度上重复自己。 我的问题是:
- 为什么PostGIS不能聪明地在查询#1中使用空间索引?
- 为什么查询#2的性能比查询#1要好得多,考虑到它们都没有使用索引?
- 有什么建议可以使查询#3更美观? 或者是否有更好的方法构造一个执行相同操作的查询?