为什么PostgreSQL在此查询中进行顺序扫描而不是索引扫描?
我正在使用OpenStreetMap osm2pgsql数据库。其中一个表(planet_osm_line)有两个索引字段:osm_id(int,主键)和way(postgis几何体) 我想找出哪些街道与特定街道相交,我通过它的osm_id知道。所以我:为什么PostgreSQL在此查询中进行顺序扫描而不是索引扫描?,postgresql,openstreetmap,postgis,Postgresql,Openstreetmap,Postgis,我正在使用OpenStreetMap osm2pgsql数据库。其中一个表(planet_osm_line)有两个索引字段:osm_id(int,主键)和way(postgis几何体) 我想找出哪些街道与特定街道相交,我通过它的osm_id知道。所以我: SELECT name, * FROM planet_osm_line WHERE highway IS NOT NULL AND osm_id != 126021312 AND ST_Intersects(way, (SELECT way F
SELECT name, * FROM planet_osm_line
WHERE highway IS NOT NULL
AND osm_id != 126021312
AND ST_Intersects(way, (SELECT way FROM planet_osm_line WHERE osm_id = 126021312 LIMIT 1))
运行大约需要10秒
相反,如果我取出该子查询并单独运行,它看起来如下所示:
SELECT name, * FROM planet_osm_line
WHERE highway IS NOT NULL
AND osm_id != 126021312
AND ST_Intersects(way, '010200002031BF0D000D000000E17...')
运行大约需要0.47秒
在第一个查询和第二个查询上运行EXPLAIN会给我一个关于差异的提示
第一:
Seq Scan on planet_osm_line (cost=2.09..614596.67 rows=628706 width=1079)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND st_intersects(way, $0))
InitPlan 1 (returns $0)
-> Limit (cost=0.43..2.09 rows=1 width=249)
-> Index Scan using planet_osm_line_pkey on planet_osm_line planet_osm_line_1 (cost=0.43..3.76 rows=2 width=249)
Index Cond: (osm_id = 126021312)
行星osm线上的序列扫描(成本=2.09..614596.67行=628706宽度=1079)
过滤器:((高速公路不为空)和(osm_id 126021312)与st_相交(道路,$0))
InitPlan 1(返回$0)
->限制(成本=0.43..2.09行=1宽=249)
->使用planet_osm_line planet_osm_line 1上的planet_osm_line_pkey进行索引扫描(成本=0.43..3.76行=2宽=249)
索引条件:(osm_id=126021312)
第二:
Index Scan using planet_osm_line_index on planet_osm_line (cost=0.41..4.25 rows=1 width=1079)
Index Cond: (way && '010200002031BF0D000D000000E17...'::geometry)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND _st_intersects(way, '010200002031BF0D000D000000E17...'::geometry))
使用planet_osm_line_索引对planet_osm_line进行索引扫描(成本=0.41..4.25行=1宽度=1079)
索引条件:(方式和“010200002031BF0D000D000000E17…”:几何)
过滤器:((高速公路不为空)和(osm_id 126021312)和_st_相交(道路,'010200002031BF0D000D000000E17…'::几何图形))
为什么PostgreSQL在第一个页面上进行seq扫描,在第二个页面上进行索引扫描?有没有办法在不发出两个查询的情况下解决这个问题?重写您的查询,这样您就不用在ST_Intersects中有子查询,而是在FROM中有一个交叉连接,然后它将受到WHERE中的相交的限制(这也隐式地执行&,即边界框检查,它将命中空间索引).
重写您的查询,以便在FROM中有一个交叉连接,而不是在ST_Intersects中有一个子查询,它将受到WHERE中的交叉连接的限制(这也隐式地执行&,即边界框检查,它将命中空间索引)
重写您的查询,以便在FROM中有一个交叉连接,而不是在ST_Intersects中有一个子查询,它将受到WHERE中的交叉连接的限制(这也隐式地执行&,即边界框检查,它将命中空间索引)
重写您的查询,以便在FROM中有一个交叉连接,而不是在ST_Intersects中有一个子查询,它将受到WHERE中的交叉连接的限制(这也隐式地执行&,即边界框检查,它将命中空间索引)
这种方式似乎很好(部分回答了我的问题): 对它的解释表明,PostgreSQL似乎在做我首先想要做的事情:
Nested Loop (cost=6.80..577.98 rows=7451 width=1108)
-> Index Scan using planet_osm_line_pkey on planet_osm_line l2 (cost=0.43..3.76 rows=2 width=249)
Index Cond: (osm_id = 126021312)
-> Bitmap Heap Scan on planet_osm_line l1 (cost=6.37..286.48 rows=63 width=1108)
Recheck Cond: (way && l2.way)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND _st_intersects(way, l2.way))
-> Bitmap Index Scan on planet_osm_line_index (cost=0.00..6.36 rows=206 width=0)
Index Cond: (way && l2.way)
嵌套循环(成本=6.80..577.98行=7451宽度=1108)
->使用planet_osm_line_pkey在planet_osm_line l2上进行索引扫描(成本=0.43..3.76行=2宽度=249)
索引条件:(osm_id=126021312)
->planet_osm_行l1上的位图堆扫描(成本=6.37..286.48行=63宽度=1108)
重新检查条件:(方式和二级方式)
过滤器:((高速公路不为空)和(osm_id 126021312)和_st_相交(路,l2.way))
->planet_osm_line_索引上的位图索引扫描(成本=0.00..6.36行=206宽度=0)
索引条件:(方式和二级方式)
不过,我仍然很好奇为什么第一个查询的行为与此不同。这种方式似乎很好(部分回答了我的问题): 对它的解释表明,PostgreSQL似乎在做我首先想要做的事情:
Nested Loop (cost=6.80..577.98 rows=7451 width=1108)
-> Index Scan using planet_osm_line_pkey on planet_osm_line l2 (cost=0.43..3.76 rows=2 width=249)
Index Cond: (osm_id = 126021312)
-> Bitmap Heap Scan on planet_osm_line l1 (cost=6.37..286.48 rows=63 width=1108)
Recheck Cond: (way && l2.way)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND _st_intersects(way, l2.way))
-> Bitmap Index Scan on planet_osm_line_index (cost=0.00..6.36 rows=206 width=0)
Index Cond: (way && l2.way)
嵌套循环(成本=6.80..577.98行=7451宽度=1108)
->使用planet_osm_line_pkey在planet_osm_line l2上进行索引扫描(成本=0.43..3.76行=2宽度=249)
索引条件:(osm_id=126021312)
->planet_osm_行l1上的位图堆扫描(成本=6.37..286.48行=63宽度=1108)
重新检查条件:(方式和二级方式)
过滤器:((高速公路不为空)和(osm_id 126021312)和_st_相交(路,l2.way))
->planet_osm_line_索引上的位图索引扫描(成本=0.00..6.36行=206宽度=0)
索引条件:(方式和二级方式)
不过,我仍然很好奇为什么第一个查询的行为与此不同。这种方式似乎很好(部分回答了我的问题): 对它的解释表明,PostgreSQL似乎在做我首先想要做的事情:
Nested Loop (cost=6.80..577.98 rows=7451 width=1108)
-> Index Scan using planet_osm_line_pkey on planet_osm_line l2 (cost=0.43..3.76 rows=2 width=249)
Index Cond: (osm_id = 126021312)
-> Bitmap Heap Scan on planet_osm_line l1 (cost=6.37..286.48 rows=63 width=1108)
Recheck Cond: (way && l2.way)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND _st_intersects(way, l2.way))
-> Bitmap Index Scan on planet_osm_line_index (cost=0.00..6.36 rows=206 width=0)
Index Cond: (way && l2.way)
嵌套循环(成本=6.80..577.98行=7451宽度=1108)
->使用planet_osm_line_pkey在planet_osm_line l2上进行索引扫描(成本=0.43..3.76行=2宽度=249)
索引条件:(osm_id=126021312)
->planet_osm_行l1上的位图堆扫描(成本=6.37..286.48行=63宽度=1108)
重新检查条件:(方式和二级方式)
过滤器:((高速公路不为空)和(osm_id 126021312)和_st_相交(路,l2.way))
->planet_osm_line_索引上的位图索引扫描(成本=0.00..6.36行=206宽度=0)
索引条件:(方式和二级方式)
不过,我仍然很好奇为什么第一个查询的行为与此不同。这种方式似乎很好(部分回答了我的问题): 对它的解释表明,PostgreSQL似乎在做我首先想要做的事情:
Nested Loop (cost=6.80..577.98 rows=7451 width=1108)
-> Index Scan using planet_osm_line_pkey on planet_osm_line l2 (cost=0.43..3.76 rows=2 width=249)
Index Cond: (osm_id = 126021312)
-> Bitmap Heap Scan on planet_osm_line l1 (cost=6.37..286.48 rows=63 width=1108)
Recheck Cond: (way && l2.way)
Filter: ((highway IS NOT NULL) AND (osm_id <> 126021312) AND _st_intersects(way, l2.way))
-> Bitmap Index Scan on planet_osm_line_index (cost=0.00..6.36 rows=206 width=0)
Index Cond: (way && l2.way)
嵌套循环(成本=6.80..577.98行=7451宽度=1108)
->使用planet_osm_line_pkey在planet_osm_line l2上进行索引扫描(成本=0.43..3.76行=2宽度=249)
索引条件:(osm_id=126021312)
->planet_osm_行l1上的位图堆扫描(成本=6.37..286.48行=63宽度=1108)
重新检查条件:(方式和二级方式)
过滤器:((高速公路不为空)和(osm_id 126021312)和_st_相交(路,l2.way))
->planet_osm_line_索引上的位图索引扫描(成本=0.00..6.36行=206宽度=0)
索引条件:(方式和二级方式)
不过,我仍然很好奇为什么第一个查询的行为与此不同。(从planet_osm_行中选择路径,其中osm_id=126021312 LIMI)