Как я могу оптимизировать pgrouting для скорости?

22

Я использую pgrouting в базе данных postgis, созданной с помощью osm2pgrouting. Он работает очень хорошо на ограниченном наборе данных (3,5 тыс. Путей, поиск по кратчайшему пути A * <20 мс).

Однако, так как я импортировал большую ограничительную рамку (122 тыс. Путей) из europe.osm, производительность сильно упала (самый короткий путь стоит около 900 мс).

Я думаю, что при использовании A * большинство этих ребер никогда не будут посещаться, поскольку они находятся вне пути.

Что я сделал до сих пор в попытке улучшить скорость:

  • Поместить индекс в столбец геометрии (без заметного эффекта)
  • Увеличил мою память с 8 ГБ до 16 ГБ
  • Измените параметры памяти postgresql (shared_buffers ,ffective_cache_size) с (128 МБ, 128 МБ) на (1 ГБ, 2 ГБ) (без заметного эффекта)

У меня такое ощущение, что большая часть работы выполняется в библиотеке C Boost, где создается график, поэтому оптимизация postgresql не даст мне намного лучших результатов. Поскольку я делаю небольшие изменения в наборе строк, которые я выбираю для A * для каждого поиска, я немного боюсь, что библиотека boost не сможет кэшировать мой график и должна каждый раз перестраивать все ребра 122k (хотя она будет использовать только очень ограниченное подмножество каждого запроса). И я понятия не имею, сколько потрачено на это по сравнению с реальным поиском по кратчайшему пути.

Кто-нибудь из вас использует pgrouting в наборе данных OSM 122k или выше? Какую производительность мне ожидать? Какие настройки влияют на производительность больше всего?

MRG
источник
2
Я не эксперт по pgrouting, но можете ли вы кешировать результаты, например, если вы знаете, что всегда используется общий суб-маршрут, можете ли вы его предварительно кэшировать? следовательно, вы должны делать меньше поисков? Кроме того, фургон вы ограничиваете поиски Артериалами и коллекционерами?
Дассуки
1
Я разрешаю бесплатный поиск банкоматов, так что я не думаю, что могу многое предположить для суб-маршрутов. Также я кеширую результаты поисков за последние x минут, но это не помогает мне для новых поисков. У меня есть ощущение, что A * на этом размере все еще должен быть очень быстрым, пока я могу сохранять статичность всего графика в памяти. Должны быть люди, которые направляют этот путь по всей стране, которые знают, как улучшить производительность.
MRG
1
Другой вариант - построить матрицу O / D (матрица происхождения / назначения). Это техника, которую мы используем в дорожной инженерии. разбить сеть на зоны, скажем, в большом городе может быть 100 зон. В каждой зоне будет фиктивный центроид. Подключите центроид к вашей сети через фиктивную ссылку. Затем вы можете перемоделировать всю свою сеть как 100 x 100 поездок (всего 10 000 поездок). Когда пользователь выполняет поиск, pgrouting должен найти маршрут, закрытый для центроида или фиктивной ссылки на стороне отправления и назначения.
Дассуки
2
Разве вы не получаете странные результаты, если кто-то хочет перейти из одной зоны в другую, но он проходит через свои центроиды? Или вы используете это только когда зоны находятся дальше друг от друга? Ваше решение имеет смысл, если клиенты хотят быстрее всего добраться от А до Б, но в моем случае мне приходится иметь дело с клиентами, которые хотят гулять, ездить на велосипеде и т. Д. Для отдыха и хотели бы выбирать уникальные маршруты и не быть вынужденными идти по стандартному маршруту.
MRG
3
Если вы ищете мультимодальное решение (велосипед, прогулка, общественный транспорт, поездка), вам действительно стоит взглянуть на Портленд, сайт мультимодальной маршрутизации Орегонского TriMet, который использует OpenTripPlanner: trimet.org/news/releases/oct15-rtp. htm
RyanDalton

Ответы:

10

Когда вы сталкиваетесь с такими задачами, ваша основная цель - быть рациональным. Не меняйте параметры, основываясь на «внутреннем чувстве». Хотя кажется, что кишка работает для Голливуда, это не для нас, живущих в реальном мире. Ну, по крайней мере, не моя интуиция ;-).

Вам следует:

  1. установить пригодную для повторения метрику (например, время, необходимое для запроса pgrouting)

  2. сохранить результаты метрик в электронной таблице и усреднить их (отбросить лучшие и худшие). Это скажет вам, если изменения, которые вы делаете, идут в правильном направлении

  3. Контролируйте ваш сервер, используя top и vmstat (при условии, что вы используете * nix) во время выполнения запросов и ищите существенные шаблоны: много операций ввода-вывода, высокая загрузка процессора, свопинг и т. д. Если процессор ожидает ввода-вывода, попробуйте улучшить производительность диска (это должно быть легко, см. ниже). Если вместо этого процессор на 100% без какой-либо значительной активности диска, вам нужно найти способ улучшить запрос (это, вероятно, будет сложнее).

Для простоты я предполагаю, что сеть здесь не играет существенной роли.

Улучшение производительности базы данных

Обновите до последней версии Postgres. Версия 9 намного лучше, чем предыдущие версии. Это бесплатно, поэтому у вас нет причин, нет.

Прочитайте книгу, которую я рекомендовал уже здесь .

Вы действительно должны прочитать это. Я считаю, что соответствующие главы для этого дела 5,6,10,11

Улучшение производительности диска

  1. Получите SSD-накопитель и поместите на него всю базу данных. Производительность чтения, скорее всего, увеличится в четыре раза, а производительность записи также должна значительно улучшиться

  2. назначьте больше памяти для postgres. В идеале вы должны быть в состоянии выделить достаточно памяти, чтобы вся (или самая горячая часть) могла быть кэширована в памяти, но не слишком много, чтобы произошла перестановка. Обмен очень плох. Это описано в книге, процитированной в предыдущем абзаце

  3. отключите atime на всех дисках (добавьте параметры noatime в fstab)

Улучшение производительности запроса

Используйте инструменты, описанные в приведенной выше книге, чтобы проследить ваши запросы и найти остановки, которые стоит оптимизировать.

Обновить

После комментариев я посмотрел исходный код хранимой процедуры

https://github.com/pgRouting/pgrouting/blob/master/core/src/astar.c

и кажется, что после того, как запрос был настроен, улучшений не остается, так как алгоритм работает полностью в памяти (и, к сожалению, только на одном процессоре). Боюсь, что ваше единственное решение - найти лучший / более быстрый алгоритм или алгоритм, который может работать в многопоточном режиме, а затем интегрировать его с postgres, либо создав библиотеку типа pgrouting, либо используя некоторое промежуточное программное обеспечение для извлечения данных (и, возможно, кеширования) и скормить это алгоритму.

НТН

unicoletti
источник
Я прочитал части книги, которую вы рекомендуете. Мой набор данных все еще достаточно мал, чтобы полностью поместиться в памяти, поэтому я думаю, что производительность диска не должна быть узким местом (я лучше проверю свои ресурсы при тестировании, чтобы подтвердить это). Я думаю, что Postgresql вступает в игру только в процессе pgrouting, когда он просто выбирает * из таблицы, чтобы заполнить библиотеку C Boost строками / кортежами для выполнения реального поиска ((может кто-то это подтвердить), поэтому я боюсь, что нет много чего можно получить в самом Postgresql. Ваш ответ кажется очень хорошим для производительности Postgresql, но, возможно, не так для pgrouting конкретной производительности.
mrg
@ mrg Я действительно думал об этом, но хотел быть уверен, что ты не упустил низко висящий фрукт. Думая об этом, вы пошли от 20 мс для 3.5k до 900 мс для 122k, что, imho, не совсем плохо. Удачи
unicoletti
Твердотельные накопители действительно повышают производительность (скорость, схожую с тем, что и кэширование)
Mapperz
По моему опыту, если использовать pgrouting для всего набора данных (таблицы), то от Postgres не будет большой пользы. Индекс даже не используется, поэтому его бесполезно. По каждому запросу вся таблица загружается в память. общие буферы и кеши также не дают никакого преимущества в производительности, потому что каждый запрос загружает всю таблицу в память. Если кому-то удалось повторно использовать загруженные данные в памяти для последующих запросов, сообщите нам об этом. Единственное возможное увеличение производительности, которое я вижу в накопителях SDD, но я никогда не проверял это. Больше памяти позволяет только больше параллельных запросов, но не производительность.
Марио Милер
8

У меня точно такая же проблема, и я собирался спросить в списках рассылки, так что спасибо всем!

Я использую Shooting Star с миллионом с половиной строк в таблице маршрутизации. На его вычисление уходит почти десять секунд. С 20 тысячами строк это занимает почти три секунды. Мне нужна Падающая звезда, потому что мне нужны ограничения на поворот.

Вот несколько идей, которые я пытаюсь реализовать:

  • На SQL, где pgRouting получает пути, используйте st_buffer, чтобы не все, а только «соседние» пути:

    выберите * из shorttest_path_shooting_star ('ВЫБРАТЬ маршрут. * ИЗ маршрутизации маршрутизации, (выберите st_buffer (st_envelope (st_collect (geometry))), 4) в качестве геометрии из маршрутизации, где id =' || source_ || 'или id =' || target | | ') e ГДЕ rout.geometry && e.geometry', источник, цель, правда, правда);

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

  • Быстрые маршруты кешируются

Как предложил Дассуки, я буду кешировать некоторые «полезные» маршруты, поэтому, если расстояние слишком велико, он может пройти по этим быстрым маршрутам и просто должен найти выход в них и из них.

  • Таблица разделов по ГИС-индексу

Но я полагаю, что, если речь идет о памяти, это на самом деле не имеет значения ... Все равно стоит это проверить.

Пожалуйста, продолжайте писать, если найдете другую идею.

Кроме того, вы знаете, есть ли какой-нибудь скомпилированный pgRouting для Postgres9?

Délawen
источник
+1 Кажется, здесь есть несколько полезных и конструктивных идей. Обратите внимание, что если вы хотите, чтобы на ваши вопросы отвечали, то лучше сформулировать их как новый вопрос. Наш FAQ расскажет вам, как действовать.
whuber
Делавен, я тоже думал о вашей первой идее (ST_Buffer) и предвидел ту же проблему. Преимущество, однако, может заключаться в 2 путях: набор данных меньше и, следовательно, быстрее, и, поскольку большая часть обработки выполняется в Postgresql, у вас снова есть способы оптимизировать его. Я использую Ubuntu 11, где postgresql 8.4 - последняя версия.
mrg
mrg, я без особых проблем скомпилировал pgRouting на Ubuntu Maverick для PostgreSQL 9.0. Postgis для PostgreSQL 9.0 можно найти здесь: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main amd64 Пакеты
Делавен
Я придумал 2 идеи. 1) Сочетание «быстрых маршрутов в кеше» и «st_buffer». Таким образом, вы гарантируете поиск маршрута, и люди не будут вынуждены идти по одному и тому же маршруту. 2) Используйте только postgis, чтобы заполнить статический граф (с помощью Boost (C), nx_spatial (Python), neo4j (Java) и т. Д.) И повторно использовать этот граф для каждого поискового запроса.
Мрг
Как насчет снижения стоимости (то есть повышения предпочтения) для «быстрых» краев, таких как шоссе, когда расстояние между началом и концом больше, чем порог? Коэффициент усиления также может быть связан с расстоянием: больше для более длинных расстояний, меньше для более коротких.
Unicoletti
5

Мы только что создали ветку в git для кратчайшего пути с ограниченным ходом @ https://github.com/pgRouting/pgrouting/tree/trsp

Извините, но документации пока нет, но если вы зададите вопросы в списке pgRouting, я вывешу там и отвечу. Этот код работает намного быстрее падающей звезды и основан на алгоритме Дейкстры.

-Стив

Стивен Вудбридж
источник
0

У меня есть исходная таблица маршрутов, которая содержит ~ 1200000 ребер. На моем i7 с SSD создание маршрута занимает 12 секунд. Моя идея повысить производительность - разделить таблицу границ на несколько таблиц уровней масштабирования. Я имею в виду уровень, который идентичен плитке Google. Например, на 8-м уровне масштабирования у меня 88 таблиц. Каждая таблица содержит подмножество дорог, и их области перекрывают друг друга, поэтому для расчета маршрута между двумя точками, расположенными на расстоянии 290 км друг от друга, требуется 2 секунды. На 9-м уровне время расчета падает до 0,25 сек и у нас 352 таблицы. Воссоздание всех графиков в случае редактирования дорог занимает не более часа. Радикальный способ увеличить скорость маршрутизации - использовать алгоритм Флойда-Варшалла. Но никто не знает, сколько нужно, чтобы вычислить матрицу предшественника на таком количестве ребер.

Vadym
источник