如何优化注浆速度?


22

我在通过osm2pgrouting创建的postgis数据库上使用pgrouting。它在有限的数据集上表现出色(3.5k种方式,所有最短路径A *搜索均<20 ms)。

但是,由于我从Europe.osm导入了一个更大的边界框(122k方向),因此性能下降了很多(最短路径的成本约为900ms)。

我认为使用A *不会使这些边缘中的大多数受到干扰。

到目前为止,我为提高速度所做的工作:

  • 在几何列上放置索引(无明显影响)
  • 我的内存从8GB增加到16GB
  • 将Postgresql内存设置(shared_buffers,effective_cache_size)从(128MB,128MB)更改为(1GB,2GB)(无明显效果)

我感觉大多数工作都在制作图形的C Boost库中完成,因此优化postgresql不会给我带来更好的结果。当我对每次搜索选择的A *行集合进行细微更改时,我有点担心boost库无法缓存我的图形,并且每次都必须重建所有122k边(即使它只会使用非常每个查询的限制子集)。而且我不知道与实际最短路径搜索相比,花了多少钱。

你们中有人在122k或更高版本的OSM数据集上使用注浆吗?我应该期待什么表现?哪些设置对性能的影响最大?


2
我不是专家,但是您可以缓存结果吗,例如,如果您知道始终使用公用子路由,则可以对其进行预缓存吗?因此,您必须减少搜索量?另外,您将搜寻范围限制在动脉和收藏家吗?
dassouki

1
我允许免费搜索atm,所以我不认为我可以为子路线承担很多责任。另外,我正在缓存最近x分钟的搜索结果,但这对我的新搜索没有帮助。我有一个感觉,只要我可以将整个图形保持在内存中,此尺寸上的A *应该仍然非常快。必须有在整个国家/地区使用这种方法的人,他们知道如何提高绩效。
2011年

1
另一种选择是建立一个O / D矩阵(起点/终点矩阵)。这是我们在流量工程中使用的技术。将网络划分为多个区域,因此,假设一个大城市可能有100个区域。每个区域将具有一个虚拟质心。通过虚拟链接将质心连接到网络。然后,您可以将整个网络重塑为100 x 100次行程(总共10,000次行程)。当用户进行搜索时,灌浆必须在始发端和目标端找到一条与质心或虚拟链接不相关的路线。
dassouki 2011年

2
如果有人想从一个区域跳到下一个区域,但又通过质心被路由,您不会得到奇怪的结果吗?还是仅在区域分开时才使用此功能?如果客户想要从A到B最快,那么您的解决方案最有意义,但是在我的情况下,我不得不与那些想走路,骑自行车等以休闲,想选择独特路线而不被迫走的客户打交道通过标准路线。
2011年

3
如果您正在寻找一种多式联运解决方案(自行车,步行,公共交通,驾车),则应该看看俄勒冈州波特兰市的TriMet多式联运选址站点,该站点使用OpenTripPlanner:trimet.org/news/releases/oct15-rtp。 htm
RyanDalton

Answers:


10

当面对这样的任务时,您的主要目标是保持理性。不要基于“胆量感觉”改变参数。尽管直觉似乎对好莱坞有效,但对生活在现实世界中的我们却不起作用。好吧,至少不是我的直觉;-)。

你应该:

  1. 建立可用的和可重复的度量标准(例如查询查询所需的时间)

  2. 将指标结果保存在电子表格中并取平均值(最好和最差)。这将告诉您所做的更改是否朝着正确的方向发展

  3. 在查询运行时使用top和vmstat监视您的服务器(假设您在* nix上),并查找重要的模式:大量io,高cpu,交换等。如果cpu在等待i / o,则尝试改善磁盘性能(这应该很容易,请参阅下文)。如果CPU的100%没有足够的磁盘实用性,则必须找到一种改进查询的方法(这可能会更难)。

为了简单起见,我假设网络在这里没有扮演任何重要的角色。

改善数据库性能

升级到最新的Postgres版本。版本9比以前的版本好得多。它是免费的,所以您没有理由不这样做。

这里阅读我推荐的书。

您确实应该阅读它。我相信此案的相关章节是5,6,10,11

改善磁盘性能

  1. 获取一个SSD驱动器,然后将整个数据库放入其中。读取性能很可能会翻两番,写入性能也应该从根本上提高

  2. 为postgres分配更多的内存。理想情况下,您应该能够分配足够的内存,以便可以将整个(或最热的部分)缓存到内存中,但又不要缓存太多,以免发生交换。交换非常不好。上一段引用的书对此进行了介绍

  3. 在所有磁盘上禁用atime(将noatime选项添加到fstab)

提高查询性能

使用上面引用的书中描述的工具来跟踪您的查询并查找值得优化的站点。

更新资料

注释之后,我查看了存储过程的源代码

https://github.com/pgRouting/pgrouting/blob/master/core/src/astar.c

而且似乎已经调整了查询​​后,由于该算法完全在内存中运行(不幸的是仅在一个CPU上运行),因此没有太多改进的余地。恐怕您唯一的解决方案是找到一种更好/更快的算法,或者一种可以运行多线程的算法,然后将其与postgres集成,方法是创建像pgrouting这样的库,或者使用某种中间件来检索数据(并缓存它),然后将其提供给算法。

高温超导


我已经阅读了您推荐的书的一部分。我的数据集仍然很小,无法完全放入内存,因此我认为磁盘性能不应成为瓶颈(我会在测试时更好地检查资源以确认这一点)。我认为Postgresql仅在进行简单的select * from table来向C Boost库提供行/元组以执行真正的搜索时才在注浆过程中起作用((有人可以确认这一点),所以我担心没有在Postgresql本身中有很多收获。您的回答似乎对Postgresql性能非常好,但对于灌输特定性能却可能不是那么好
2011年

@mrg我实际上已经想到了这一点,但是我想确保您没有遗漏那些低落的果实。考虑到这一点,您从3.5ms的20ms变为122k的900ms,这并不完美。祝你好运
unicoletti

固态硬盘确实提高了性能(与缓存的速度类似)
Mapperz

以我的经验,如果对所有数据集(表)使用pgrouting,那么Postgres引擎并不会带来太大的好处。索引甚至没有使用,因此它毫无用处。在每个查询中,整个表都被加载到内存中。共享缓冲区和缓存也没有带来任何性能优势,因为每个查询都将所有表加载到内存中。如果有人成功重用了内存中加载的数据用于后续查询,请告诉我们。我在SDD驱动器中只能看到可能的性能提高,但是我从未测试过。更多的内存仅允许更多的并发查询,而不是性能。
Mario Miler

8

我也有同样的问题,正要在邮件列表中询问,所以谢谢大家!

我在路由表上使用百万行半的射击之星。计算大约需要十秒钟。对于2万行,将花费近三秒钟。我需要流星,因为我需要转弯限制。

这是我尝试实现的一些想法:

  • 在pgRouting可以获取方法的SQL上,请使用st_buffer,以便它不会获取所有方法,而只是“附近”的方法:

    select * from shortest_path_shooting_star('SELECT rout。* FROM routing rout,(select st_buffer(st_envelope(st_collect(geometry)),4)作为来自路由的几何,其中id ='|| source_ ||'或id ='|| target | |')e WHERE rout.geometry && e.geometry',来源,目标,true,true);

它提高了性能,但是如果该方式需要超出缓冲区范围,它可能会返回“找不到路径”错误,所以...大缓冲区吗?几次调用增加缓冲区直到找到方法?

  • 快速路线已缓存

就像dassouki建议的那样,我将缓存一些“有用的”路线,因此,如果距离太长,它可以通过这些快速路线,而只需要找到进出它们的出路即可。

  • 按GIS索引划分表

但是我想,如果涉及到内存,那并不重要……无论如何都应该对其进行测试。

请继续发布,如果您发现其他想法。

另外,您是否知道Postgres9是否有一些已编译的pgRouting?


+1这里似乎有一些有用和建设性的想法。请注意,如果您想回答问题,那么最好将其表述为新问题。我们的常见问题解答将告诉您如何进行。
ub

Délawen,我也一直在考虑您的第一个想法(ST_Buffer),并预见到同样的问题。但是,优点可能有两种:数据集较小,因此速度更快,并且随着更多的处理在Postgresql中完成,您又有办法对其进行优化。Atm我正在使用Ubuntu 11,其中PostgreSQL 8.4是最新版本。
mrg 2011年

MRG,我在PostgreSQL 9.0的Ubuntu Maverick上编译了pgRouting,没有太大问题。对PostgreSQL 9.0的PostGIS可以在这里找到:ppa.launchpad.net/pi-deb/gis/ubuntu特立独行/ amd64上主要的软件包
Délawen

我提出了两个想法。1)“快速路由已缓存”和“ st_buffer”的组合。这样一来,您可以保证找到一条路线,而不会有人被迫走同一条路线。2)仅使用postgis填充静态图形(使用Boost(C),nx_spatial(Python),neo4j(Java)等),并将该图形用于每个搜索查询。
2011年

当起点和终点之间的距离大于阈值时,如何降低“快速”边缘(如高速公路)的成本(即提高优先级)呢?提升因子也可能与距离有关:距离越长,距离越短。
unicoletti


0

我有一个包含〜1200000边的源路由表。在配备SSD的i7上,创建路由需要12秒。我提高性能的想法是将边缘表分成几个缩放级别表。我的意思是和Google Tiles一样的水平。例如,在第8缩放级别,我有88张桌子。每个表都包含道路的子集,并且它们的区域彼此重叠,以便计算彼此之间相距不超过290公里的两个点之间的路线需要2秒钟。在第9级,计算时间下降到0.25秒,我们有352张桌子。在我们编辑道路的情况下,所有图形的创建不会超过一个小时。提高路由速度的根本方法是使用Floyd-Warshall算法。但是没有人知道在那么多边缘计算前身矩阵需要多少费用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.