4

背景:

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

  • 带有标签的 osm 节点;

  • 带有权重的 osm 边(即从 .osm 文件中的“方式”中提取的两个节点之间的边)。

形成边的节点,在相同的“路”集合中应该具有与那些路相同的标签,即,作为高速公路的“路”节点集合中的每个节点都应该具有“高速公路”标签。

我需要这种结构来轻松生成基于各种过滤器的图,例如仅由节点和边组成的图,即高速公路,或“人行道”图等。

问题:

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

  • 所有节点到“节点”表(具有各自的坐标列) - 好的,在我的情况下大约有 9,000,000 行:

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

  • 'edges' 表的所有方式(通常一种方式会创建一些边) - 好的,还有大约 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 每 55-60 秒显示一次 'echo "$i\n"' 的输出(如果 'edges' 表的大小超过 9,000,000 行,就像我的情况一样,这可能需要 17 年以上才能完成)。

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

尝试计算边的权重(距离)的脚本存在相同的问题(选择所有边,取一条边,然后从“节点”表中选择该边的两个节点,然后计算距离,然后更新边表)。

问题:

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

4

2 回答 2

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 表、解析 OSM 文件的 perl 代码并将其导入您的 MySQL 数据库。

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

祝你好运

于 2011-04-24T21:20:09.580 回答
3

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

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

其次,获取整个表并在数据库之外对其进行处理不是正确的方法。关系数据库真正擅长的是处理整个过程。

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

因此,如果我们忽略第一个问题,只是为了展示这个概念,就说只有两条边连接到一个节点,并且每个节点都有两个标签字段。标签 1 和标签 2。然后它在 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;

如果您禁用应该非常快的索引。

再说一次,如果我理解你的话。

于 2011-04-29T07:12:29.097 回答