目标
我想为可布线图中的每一对顶点运行pgr_dijkstra
.我有一个简单的脚本,它获取每一对顶点并对数据库启动pgr_dijkstra
.
这将是很好的使用PostgreSQL parallel query的能力来加速它.
我想实现一个"容易"的速度,而不需要实现像contractions这样的高级代码.
问题
尽管我可以看到,对于我的一些表,explain analyze
显示了一个涉及Gather
和Parallel Seq Scan
的计划,但try 在启用"并行"参数和PARALLEL SAFE
关键字的情况下运行pgr_dijkstra
实际上会使运行速度变慢.
输入数据
我有一个启用了PostGIS的数据库,其中有大约OSM
个数据是用osm2pgsql
导入的:
Data | Size |
---|---|
Nodes (vertices) table | 730 vertices |
Nodes (vertices) table | 160 kB |
Edges table | 1100 vertices |
Edges table | 656 kB |
PostgreSQL和系统配置
CPU:第11代英特尔酷睿i7-1165G7
PostgreSQL parameter | Value |
---|---|
min_parallel_table_scan_size |
8kB |
force_parallel_mode |
off |
parallel_setup_cost |
10 |
parallel_tuple_cost |
0.001 |
max_parallel_workers_per_gather |
8 |
max_parallel_workers |
8 |
max_worker_processes |
8 |
我已经将force_parallel_mode
设置为每this recommendation到off
,但即使是on
也没有什么不同.
将parallel_tuple_cost
从缺省值更改为0.001
does not seem to help.
查询和结果
我已经设置了一个非常简单的pgr_dijkstra
呼叫,有SAFE
和没有SAFE
,源/目标顶点的id
都是硬编码的:
CREATE OR REPLACE
FUNCTION pgr_parallel()
RETURNS VOID
AS $$
BEGIN
PERFORM pgr_dijkstra(
'
SELECT gid AS id,
source,
target,
length_m AS cost
FROM edges_table
WHERE
NOT source IS NULL
AND
NOT target IS NULL
AND
NOT the_geom IS NULL
AND NOT length_m IS NULL
',
ARRAY[161]
,
ARRAY[639]
,
directed := false
);
END;
$$ LANGUAGE 'plpgsql'
PARALLEL SAFE;
我有一个简单的脚本,它调用这个函数N次,它似乎不是以并行的方式运行的:
Type of function | Number (N) of pairs of vertices | Execution time |
---|---|---|
undefined (not parallel) | 50,000 | 67 seconds |
PARALLEL SAFE |
50,000 | 89 seconds |
作为额外的观察,我运行htop
并看到在开始时,当(并行)脚本运行时,所有8个物理核心都被使用了.但是,当脚本完成向数据库发送"任务"时,htop
显示postgres
进程只使用一个内核.
问题
如果我理解正确的话,如果有一些有意义的independent work to be done by each worker,那么查询可以被‘并行化’.在pgr_dijkstra
和任何其他最短路径查找算法的情况下,情况不是这样吗?我假设pgr_dijkstra
会获取顶点和边,然后对它们运行独立的计算.
是否有可能利用PostgreSQL
的parallel query
功能,使pgr_dijkstra
的至少某些部分能够并行运行?若有,如何处理?
Crunchy Data和Paul Ramsey在this post中使用了Note:,PARALLEL SAFE
用于包含pgr_dijkstra
的函数,但由于这一点,它是否运行得更快没有细节.