バックグラウンド:
次のデータをデータベースに保存する必要があります。
タグ付きのosmノード;
重み付きの osm エッジ (.osm ファイルの「way」から抽出された 2 つのノード間のエッジ)。
同じ 'way' セットにあるエッジを形成するノードは、これらのウェイと同じタグを持つ必要があります。つまり、ハイウェイであるノードの 'way' セット内のすべてのノードは 'highway' タグを持つ必要があります。
さまざまなフィルターに基づいてグラフを簡単に生成するには、この構造が必要です。たとえば、高速道路であるノードとエッジのみで構成されるグラフ、または「歩道」グラフなどです。
問題:
以前に空間インデックスについて聞いたことがなかったので、.osm ファイルを MySQL データベースに解析しました。
- 「ノード」テーブルへのすべてのノード(それぞれの座標列を含む)-OK、私の場合は約9,000,000行:
(INSERT INTO nodes VALUES [pseudocode]node_id,lat,lon[/pseudocode]
;
- 「エッジ」テーブルへのすべての方法 (通常、1 つの方法でいくつかのエッジが作成されます) - OK、約 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 は、CPU の 40 ~ 60% を使用する /usr/bin/mysqld プロセスを示しています。
エッジの重み (距離) を計算しようとするスクリプトにも同じ問題が存在します (すべてのエッジを選択し、エッジを取得し、「ノード」テーブルからこのエッジの 2 つのノードを選択し、距離を計算し、エッジ テーブル)。
質問:
この SQL 更新を高速化するにはどうすればよいですか? MySQL の構成設定を微調整する必要がありますか? または、PostGIS 拡張機能を備えた PostgreSQL を使用する必要がありますか? データに別の構造を使用する必要がありますか? それとも、何らかの形で空間インデックスを利用する必要がありますか?