PgRouting求解大数据量最短路径
发布于2022-04-25 23:59:21,更新于2024-06-23 15:52:24,标签:sql 文章会持续修订,转载请注明来源地址:https://meethigher.top/blog实际工作中的一个场景,类似于要做一个像地图那样,指定起终点,给出所有可行路线,本来是自己实现的,使用图的深度优先算法,结果由于数据量太大了,直接把内存算崩了。我也知道可以大而化小、分而治之、剩下小块再建立关联,可惜这样一个好的数据结构,我搞不出来。最终不得已,选用pgrouting作为替代品,但也跟原需求不太符合,这个是求最优的方式,并不是求所有。
唉,不过是一个离了开源啥也干不了的废物罢了。
也许,这才是许许多多CRUD码农,亟待突破的瓶颈!
所以,努力学习吧!
首先要有一个postgresql数据库,并开启postgis与pgrouting扩展,这里不多赘述!查看具体的安装过程。
pgRouting通过osm2pgrouting加载osm地图数据
pgr_dijkstra — pgRouting Manual (3.3)
pgrouting - 如何修复 pgr_dijkstra 错误,查询必须返回列 ‘id’、’source’、’target’ 和 ‘cost’? - 地理信息系统堆栈交换
postgresql - 如何编写一个不返回任何内容的 postgres 存储过程? - 堆栈溢出
common table expression - PostgreSQL: Query has no destination for result data - Stack Overflow
返回NULL的行级触发器导致错误:查询没有结果数据的目的地 - Thinbug
一、导入OSM数据
开源地图导出 | OpenStreetMap,通过地图导出自定义的位置信息。
进入Linux,下载地图信息,并导入信息。
1 | # 忽略证书下载后重命名为map.osm |
导入后的输出信息如下
1 | [root@rollback ~]# osm2pgrouting -f map.osm -h 192.168.10.10 -U pgrouting -d pgrouting_test -p 5432 -W meethigher --conf=/usr/share/osm2pgrouting/mapconfig_for_cars.xml rm map.osm |
推荐使用dbeaver打开,可以直接查看地图数据,也是基于OpenStreetMap的。
因为OpenStreetMap下载的数据,本身已经经过拓扑处理了,所以就可以直接进行查询。
1 | -- 函数使用说明 |
起点编号source和终点编号source是pgrouting维护的。通过dbeaver可以直观的看出起终点号。
二、Dijkstra最短路径
使用自己创建的数据库,来体验下整个流程。
1 | -- 删表 |
postgresql 单引号的转义符是$$
上面的写法就是select id, source, target, cost from xiangwan where roadname like ‘%我爱向晚%’
根据查询结果可知,经过的点号依次是1->2->3->5->6。
三、实际做法
因为每有数据来了之后,就要对拓扑图进行一次维护(对cost、source、target的维护)。
由于数据不常变化,这边就想直接使用postgresql的触发器实现。更主要的还是我懒得写代码维护了!
postgresql的触发器比较反人类,必须要基于一个触发器函数才行。这点跟mysql相比,从人性化的角度考虑,简直被吊打。
1 | -- 删除函数 |
上面的那个update xiangwan where cost is null,这么写其实有问题。
但是我的目的是只要有路径能查出来就行,所以这边特别精准是哪条路径对我作用不大。
而且,如果不加where cost is null,就会出现无限套娃的情况!
每次update之后,都要重新执行触发器。