Какую СУБД следует использовать для хранения openstreetmap в виде графика? - PullRequest
4 голосов
/ 25 апреля 2011

Справочная информация:

Мне нужно хранить в базе данных следующие данные:

  • узлы osm с тегами;

  • ребра osm с весами (то есть ребро между двумя узлами, извлеченными из 'way' из файла .osm).

Узлы, которые образуют ребра, которые являютсяв тех же «путевых» наборах должны быть те же теги, что и в этих путях, т. е. каждый узел в «путевом» наборе узлов, являющихся магистралью, должен иметь метку «магистрали».

Мне нужна эта структура, чтобылегко создать график на основе различных фильтров, например, график, состоящий только из узлов и ребер, являющихся магистралями, или график «пешеходных дорожек» и т. д.

Проблема:

Раньше я не слышал о пространственном индексе, поэтому я просто проанализировал файл .osm в базе данных MySQL:

  • все узлы в таблице узлов (с соответствующими столбцами координат) - ОКоколо 9 000 000 строк в моем случае:

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

  • все пути к таблице 'ребер'e (обычно один путь создает несколько ребер) - хорошо, около 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 секунд (что может занять более 17 лет, если размер таблицы «ребер» превышает 9 000 000 строк, как в моем случае).

Htop показывает / usr / bin / mysqldпроцесс, который занимает 40-60% ЦП.

Та же проблема существует для скрипта, который пытается вычислить вес (расстояние) ребра (выбрать все ребра, взять ребро, затем выбрать два узлаэто ребро из таблицы «узлов», затем рассчитайте расстояние, а затем обновите таблицу ребер.)

Вопрос:

Как я могу ускорить обновление SQL?Должен ли я настроить какие-либо параметры конфигурации MySQL?Или я должен использовать PostgreSQL с расширением PostGIS?Должен ли я использовать другую структуру для моих данных?Или мне как-то использовать пространственный индекс?

Ответы [ 2 ]

3 голосов
/ 29 апреля 2011

Если я вас правильно понимаю, есть две вещи для обсуждения.

Во-первых, ваша идея поместить тег шоссе в начальный и конечный узлы. Узел может иметь более одного связанного ребра, куда поместить метку со второго ребра? Или третий или четвертый, если это пересечение? Причина, по которой тег шоссе помещается в таблицу ребер в первую очередь, заключается в том, что с точки зрения реляции он и принадлежит.

Во-вторых, получить всю таблицу и обработать ее вне базы данных - неправильный путь. Что действительно хорошо для реляционной базы данных, так это заботиться обо всем этом процессе.

Я не работал с 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;

Если вы отключите индексы, это должно быть очень быстро.

Опять же, если я вас правильно понял.

3 голосов
/ 25 апреля 2011

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
Здесь вы найдете Perl-код, который будет создавать таблицы MySQL, анализировать файл OSM и импортировать его в базу данных MySQL.

Созданиеэто быстрее
Если вы выполняете массовое обновление, вам не нужно обновлять индексы после каждого обновления.
Вы можете просто отключить индексы, выполнить все свои обновления и повторно включить индекс.
Я предполагаю, что это должно быть намного быстрее.

Удачи

...