背景
我需要将以下数据存储在数据库中:
带标签的osm节点;
osm带有权重的边(即从.osm文件中'way'中提取的两个节点之间的边缘)。
形成边缘的节点,它们采用相同的“方式”集合应该具有与这些方式相同的标签,即作为高速公路的“方式”节点集中的每个节点都应该具有“高速公路”标签。 / p>
我需要这种结构,以便根据各种过滤器轻松生成图表,例如:仅由高速公路的节点和边缘组成的图形,或“脚路径”图等
问题:
之前我没有听说过空间索引,所以我只是将.osm文件解析为MySQL数据库:
(INSERT INTO nodes VALUES [pseudocode]node_id,lat,lon[/pseudocode]
;
(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扩展一起使用?我应该为我的数据使用其他结构吗?或者我应该以某种方式利用空间索引?
答案 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;
如果禁用速度非常快的索引。
再次 如果我理解你的话。