我在表的几何字段中有一百万个字符串,' geom'。我试图找到彼此交叉的线串,以便我可以从原始表中删除它们。 我在' geom'上创建了一个GIST空间索引,并将该表聚集在该索引上。有没有更有效的方法来做这个,不需要进行万亿(10 ^ 6×10 ^ 6)的比较?
SELECT (CASE WHEN A.length >= B.length THEN A.gid ELSE B.gid END)
INTO lines_self_crossing
FROM lines AS A, lines AS B
WHERE ST_Crosses(A.geom, B.geom) = true
;
我正在清理这些线路'表我使用ST_ShortestLine在400,000个宗地和40,000个道路线串之间生成。我已经删除了穿越道路或包裹的线路。该表包含来自原始宗地和其结束的道路的唯一ID。
EDIT 这是重写的查询,并解释分析输出:
explain analyze
SELECT (CASE WHEN A.length >= B.length THEN A.gid ELSE B.gid END)
INTO shortline_crosses_shortline2
FROM parcelstiug_roadciu1mwt_sl_noroadnoparcelcross AS A
JOIN parcelstiug_roadciu1mwt_sl_noroadnoparcelcross AS B
ON ST_DWithin(A.geom, B.geom, 1)
AND ST_Crosses(A.geom, B.geom) = true
WHERE A.gid <> B.gid
;
解释分析的输出:
` Nested Loop (cost=0.29..4273300.12 rows=96 width=24) (actual time=6.111..1692272.505 rows=8363188 loops=1)
-> Seq Scan on parcelstiug_roadciu1mwt_sl_noroadnoparcelcross a (cost=0.00..21795.31 rows=897431 width=76) (actual time=0.008..128.911 rows=897431 loops=1)
-> Index Scan using ptiugrciu1mwtslnrnpc_spindex on parcelstiug_roadciu1mwt_sl_noroadnoparcelcross b (cost=0.29..4.73 rows=1 width=76) (actual time=0.806..1.881 rows=9 loops=897431)
Index Cond: ((geom && st_expand(a.geom, 1::double precision)) AND (a.geom && geom))
Filter: ((a.gid <> gid) AND (a.geom && st_expand(geom, 1::double precision)) AND _st_dwithin(a.geom, geom, 1::double precision) AND _st_crosses(a.geom, geom))
Rows Removed by Filter: 74
Total runtime: 1696618.617 ms`
EDIT2指数定义如下:
CREATE INDEX ptiugrciu1mwtslnrnpc_gid
ON parcelstiug_roadciu1mwt_sl_noroadnoparcelcross
USING btree
(gid);
CREATE INDEX ptiugrciu1mwtslnrnpc_parceltayoid
ON parcelstiug_roadciu1mwt_sl_noroadnoparcelcross
USING btree
(parcel_tayoid);
CREATE INDEX ptiugrciu1mwtslnrnpc_roadgid
ON parcelstiug_roadciu1mwt_sl_noroadnoparcelcross
USING btree
(road_gid);
CREATE INDEX ptiugrciu1mwtslnrnpc_spindex
ON parcelstiug_roadciu1mwt_sl_noroadnoparcelcross
USING gist
(geom);
ALTER TABLE parcelstiug_roadciu1mwt_sl_noroadnoparcelcross CLUSTER ON ptiugrciu1mwtslnrnpc_spindex;
EDIT3:使用ST_Intersects而不是ST_Crosses将运行时间缩短为343616 ms。
答案 0 :(得分:0)
使用ST_DWithin
您只会与亲近的人进行比较。并将使用索引。我的桌子是500k行,大约需要30秒。
这是我找到一个节点断开道路网络时的例子,我比较了end / begin节点,并检查是否与另一个end / begin节点相交。
所以只能比较接近1米的那个。而不是与自己相比。
我认为价值0.0001
取决于您的项目,但很容易使用ST_Distance
进行测试。
SELECT
f.id as node_id,
g.id as line_id,
'start_node' as type
FROM ways_rto f
JOIN ways_rto g
on ST_DWithin(f.sp, g.geom, 0.0001)
and ST_Intersects(f.sp, g.geom)
and NOT ( f.sp_txt = g.sp_txt OR f.sp_txt = g.ep_txt)
WHERE f.id <> g.id
更新:我进行了另一次测试,复制了我的数据,时间是60秒。我能看到的唯一区别是我将点与线进行比较。
EXPLAIN ANALYZE
"Nested Loop (cost=0.00..10748875.97 rows=1083 width=8) (actual time=13913.424..60016.767 rows=136 loops=1)"
" -> Seq Scan on test_rto g (cost=0.00..54344.94 rows=1379094 width=140) (actual time=0.298..196.095 rows=1379094 loops=1)"
" -> Index Scan using test_rto_sp_idx on test_rto f (cost=0.00..7.74 rows=1 width=55) (actual time=0.041..0.041 rows=0 loops=1379094)"
" Index Cond: ((sp && st_expand(g.geom, 0.0001::double precision)) AND (sp && g.geom))"
" Filter: ((sp_txt <> g.sp_txt) AND (sp_txt <> g.ep_txt) AND (id <> g.id) AND (g.geom && st_expand(sp, 0.0001::double precision)) AND _st_dwithin(sp, g.geom, 0.0001::double precision) AND _st_intersects(sp, g.geom))"
" Rows Removed by Filter: 7"
"Total runtime: 60016.872 ms"