我应该使用什么DBMS将openstreetmap存储为图形?

时间:2011-04-24 20:53:23

标签: database graph postgis openstreetmap

背景

我需要将以下数据存储在数据库中:

  • 带标签的osm节点;

  • osm带有权重的边(即从.osm文件中'way'中提取的两个节点之间的边缘)。

形成边缘的节点,它们采用相同的“方式”集合应该具有与这些方式相同的标签,即作为高速公路的“方式”节点集中的每个节点都应该具有“高速公路”标签。 / p>

我需要这种结构,以便根据各种过滤器轻松生成图表,例如:仅由高速公路的节点和边缘组成的图形,或“脚路径”图等

问题:

之前我没有听说过空间索引,所以我只是将.osm文件解析为MySQL数据库:

  • 所有节点到'nodes'表(各自的坐标列) - 好吧,在我的案例中大约有9,000,000行:

(INSERT INTO nodes VALUES [pseudocode]node_id,lat,lon[/pseudocode];

  • 到'edge'表的所有方法(通常单向创建一些边) - 好的,大约9,000,000行:

(INSERT INTO edges VALUES [pseudocode]edge_id,from_node_id,to_node_id[/pseudocode];

  • 向节点添加标签,计算边缘的权重 - 问题

这是有问题的php脚本:

$query = mysql_query('SELECT * FROM edges');
$i=0;
while ($res = mysql_fetch_object($query))  {
$i++;
echo "$i\n";
$node1 = mysql_query('SELECT * FROM nodes WHERE id='.$res->from);
$node1 = mysql_fetch_object($node1);
$tag1 = $node1->tags;
$node2 = mysql_query('SELECT * FROM nodes WHERE id='.$res->to);
$node2 = mysql_fetch_object($node2);
$tag2 = $node2->tags;

mysql_query('UPDATE nodes SET tags="'.$tag1.$res->tags.'" WHERE nodes.id='.$res->from);
mysql_query('UPDATE nodes SET tags="'.$tag2.$res->tags.'" WHERE nodes.id='.$res->to);`

Nohup显示'echo'的输出$ i \ n“'每55-60秒(如果'edge'表的大小超过9,000,000行,可能需要17年才能完成,就像我的情况)。

Htop显示一个/ usr / bin / mysqld进程占用了40-60%的CPU。

尝试计算边的权重(距离)的脚本存在同样的问题(选择所有边,取边,然后从'节'表中选择此边的两个节点,然后计算距离,然后更新边缘表)。

问题:

如何更快地进行SQL更新?我应该调整任何MySQL配置设置吗?或者我应该将PostgreSQL与PostGIS扩展一起使用?我应该为我的数据使用其他结构吗?或者我应该以某种方式利用空间索引?

2 个答案:

答案 0 :(得分:3)

<强>的PostgreSQL
Openstreetmap本身使用PostgreSQL,所以我猜这是推荐的 请参阅:http://wiki.openstreetmap.org/wiki/PostgreSQL

您可以在以下位置查看OSM的数据库架构:http://wiki.openstreetmap.org/wiki/Database_Schema

因此,您可以使用OSM用于最大兼容性的相同字段,字段和索引。

<强>的MySQL
如果要将.osm文件导入MySQL数据库,请查看:
http://wiki.openstreetmap.org/wiki/OsmDB.pm
在这里,您将找到将创建MySQL表的perl代码,解析OSM文件并将其导入MySQL数据库。

加快速度
如果要批量更新,则无需在每次更新后更新索引 您可以禁用索引,执行所有更新并重新启用索引 我猜这应该快得多。

祝你好运

答案 1 :(得分:3)

如果我理解你,有两件事需要讨论。

首先,您将高速公路标记放在开始和停止节点上的想法。一个节点可以连接多个边缘,从第二个边缘放置标签?如果是十字路口,还是第三或第四?高速公路标签首先放在边缘表中的原因是从它所属的关系角度来看。

其次,获取整个表并将其处理到数据库之外是不正确的。关系数据库真正擅长的是处理整个过程。

我没有使用过mysql,我完全同意,如果迁移到PostGIS,你可能会获得更多乐趣,因为PostGIS具有更好的空间功能(即使你不需要任何空间功能来完成这个特定的任务) )从我所听到的。

因此,如果我们忽略第一个问题,只是为了显示概念,说只有两个边连接到一个节点,并且每个节点有两个标记字段。 tag1和tag2。然后在PostGIS中看起来像这样:

UPDATE nodes set tag1=edges.tags from edges where nodes.id=edges.from;
UPDATE nodes set tag2=edges.tags from edges where nodes.id=edges.to;

如果禁用速度非常快的索引。

再次 如果我理解你的话。