¿Cómo puedo optimizar pgrouting para la velocidad?


22

Estoy usando pgrouting en una base de datos postgis creada a través de osm2pgrouting. Funciona muy bien en un conjunto de datos limitado (3.5k formas, todas las rutas A * más cortas buscan <20 ms).

Sin embargo, desde que importé un cuadro delimitador más grande (122k formas) desde europe.osm, el rendimiento bajó mucho (un camino más corto cuesta alrededor de 900ms).

Creo que usar A * la mayoría de esos bordes nunca serán visitados ya que están fuera del camino.

Lo que he hecho hasta ahora en un intento de mejorar la velocidad:

  • Poner un índice en la columna de geometría (sin efecto notable)
  • Aumenté mi memoria de 8GB a 16GB
  • Cambie la configuración de memoria postgresql (shared_buffers, efectivo_caché_tamaño) de (128MB, 128MB) a (1GB, 2GB) (sin efecto notable)

Tengo la sensación de que la mayor parte del trabajo se está realizando en la biblioteca C Boost donde se está haciendo el gráfico, por lo que optimizar postgresql no me dará resultados mucho mejores. A medida que hago pequeños cambios en el conjunto de filas que selecciono para A * para cada búsqueda, tengo un poco de miedo de que la biblioteca de impulso no pueda almacenar en caché mi gráfico y tenga que reconstruir todos los 122k bordes cada vez (aunque solo usará un muy subconjunto limitado de cada consulta). Y no tengo idea de cuánto se gasta haciendo eso en comparación con la búsqueda de ruta más corta real.

¿Alguno de ustedes usa pgrouting en un conjunto de datos OSM de 122k o más? ¿Qué rendimiento debo esperar? ¿Qué ajustes afectan más el rendimiento?


2
No soy un experto en pgrouting, pero ¿puede almacenar en caché los resultados, por ejemplo, si sabe que siempre se usa una subruta común, puede precachearla? por lo tanto, tienes que hacer menos búsquedas? Además, ¿van a limitar las búsquedas a Arteriales y coleccionistas?
dassouki el

1
Permito cajeros automáticos de búsqueda gratuitos, así que no creo que pueda suponer mucho para las rutas secundarias. También estoy almacenando en caché el resultado de las búsquedas de los últimos x minutos, pero eso no me ayuda para nuevas búsquedas. Tengo la sensación de que A * en este tamaño aún debería ser realmente rápido siempre que pueda mantener todo el gráfico estático en la memoria. Debe haber personas que viajen de esta manera en un país entero que sepan cómo mejorar el rendimiento.
mrg

1
Otra opción sería construir una matriz O / D (matriz de origen / destino). Esta es una técnica que utilizamos en ingeniería de tráfico. dividir la red en zonas, así que digamos que una gran ciudad podría tener 100 zonas. Cada zona tendría un centroide ficticio. Conecte el centroide a su red a través de un enlace ficticio. Luego puede remodelar toda su red como 100 x 100 viajes (10,000 viajes en total). Cuando un usuario realiza una búsqueda, pgrouting tiene que encontrar una ruta cerrada al centroide o enlace ficticio en el lado de origen y destino.
dassouki el

2
¿No obtienes resultados extraños si alguien quiere ir de una zona a la siguiente pero se enruta a través de sus centroides? ¿O solo usa esto cuando las zonas están más separadas? Su solución tiene más sentido si los clientes quieren llegar más rápido de A a B, pero en mi caso tengo que tratar con clientes que desean caminar, andar en bicicleta, etc. por placer y desean elegir rutas únicas y no verse obligados a ir a través de la ruta estándar.
mrg

3
Si está buscando una solución multimodal (bicicleta, caminata, transporte público, manejo), debería echar un vistazo al sitio de enrutamiento multimodal TriMet de Portland, Oregón, que utiliza OpenTripPlanner: trimet.org/news/releases/oct15-rtp. htm
RyanDalton

Respuestas:


10

Cuando te enfrentas a tareas como esta, tu objetivo principal es ser racional. No cambie los parámetros basados ​​en el "presentimiento". Si bien el intestino parece funcionar para Hollywood, no lo es para nosotros que vivimos en el mundo real. Bueno, al menos no mi instinto ;-).

Debieras:

  1. establecer una métrica utilizable y repetible (como el tiempo requerido por una consulta de pgrouting)

  2. guardar los resultados de las métricas en una hoja de cálculo y promediarlos (descartar lo mejor y lo peor). Esto le dirá si los cambios que está haciendo van en la dirección correcta

  3. supervise su servidor usando top y vmstat (suponiendo que esté en * nix) mientras se ejecutan las consultas y busque patrones significativos: mucha io, CPU alta, intercambio, etc. Si la CPU está esperando E / S, intente mejorar rendimiento del disco (esto debería ser fácil, ver más abajo). Si, en cambio, la CPU está al 100% sin ninguna actividad de disco significativa, debe encontrar una manera de mejorar la consulta (esto probablemente será más difícil).

En aras de la simplicidad, supongo que la red no está desempeñando ningún papel importante aquí.

Mejora del rendimiento de la base de datos.

Actualice a la última versión de Postgres. La versión 9 es mucho mejor que las versiones anteriores. Es gratis, así que no tienes razón para no hacerlo.

Lea el libro que recomendé ya aquí .

Realmente deberías leerlo. Creo que los capítulos relevantes para este caso son 5,6,10,11

Mejora del rendimiento del disco

  1. Obtenga una unidad SSD y coloque toda la base de datos en ella. El rendimiento de lectura probablemente se cuadruplicará y el rendimiento de escritura también debería mejorar radicalmente

  2. asignar más memoria a postgres. Idealmente, debería poder asignar suficiente memoria para que la totalidad (o la parte más activa) pueda almacenarse en la memoria caché, pero no demasiado para que se produzca el intercambio. El intercambio es muy malo. Esto está cubierto en el libro citado en el párrafo anterior.

  3. deshabilite atime en todos los discos (agregue las opciones de noatime a fstab)

Mejora del rendimiento de la consulta

Use las herramientas descritas en el libro citado anteriormente para rastrear sus consultas y encontrar paradas que valga la pena optimizar.

Actualizar

Después de los comentarios, he mirado el código fuente del procedimiento almacenado

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

y parece que una vez que la consulta se ha ajustado, no hay mucho más margen de mejora ya que el algoritmo se ejecuta completamente en la memoria (y, desafortunadamente, solo en una CPU). Me temo que su única solución es encontrar un algoritmo mejor / más rápido o uno que pueda ejecutar multiproceso y luego integrarlo con postgres, ya sea creando una biblioteca como pgrouting o usando algún middleware para recuperar los datos (y almacenarlos en caché, tal vez) y alimentarlo al algoritmo.

HTH


He leído partes del libro que me recomiendan. Mi conjunto de datos todavía es lo suficientemente pequeño como para caber completamente en la memoria, por lo que creo que el rendimiento del disco no debería ser un cuello de botella (comprobaré mejor mis recursos cuando realice las pruebas para confirmar esto). Creo que Postgresql solo entra en juego en el proceso de búsqueda cuando realiza una simple selección * de la tabla para alimentar la biblioteca C Boost con filas / tuplas para realizar la búsqueda real ((alguien puede confirmar esto), así que me temo que no hay mucho que ganar en sí mismo Postgresql Su respuesta parece muy bueno para el rendimiento PostgreSQL, pero tal vez no tan pgrouting para el cumplimiento específico..
MRG

@mrg En realidad había pensado en eso, pero quería asegurarme de que no dejaras de lado la fruta baja. Pensando en ello, pasaste de 20ms por 3.5k a 900ms por 122k, lo cual, en mi opinión, no es del todo malo. Buena suerte
unicoletti

Las unidades de estado sólido aumentan el rendimiento (velocidades similares a las del almacenamiento en caché)
Mapperz

En mi experiencia, si usa pgrouting en todos los conjuntos de datos (tabla), entonces no hay un gran beneficio del motor Postgres. Index ni siquiera se usa, por lo que es inútil. En cada consulta, toda la tabla se carga en la memoria. los buffers y cachés compartidos tampoco dieron ningún beneficio de rendimiento porque cada consulta carga toda la tabla en la memoria. Si alguien ha logrado reutilizar los datos cargados en la memoria para consultas posteriores, infórmenos. Solo veo un posible aumento de rendimiento en las unidades SDD, pero nunca lo he probado. Más memoria solo permite más consultas concurrentes, no rendimiento.
Mario Miler

8

Tengo el mismo problema y estaba a punto de preguntar en las listas de correo, ¡así que gracias a todos!

Estoy usando Shooting Star con un millón y medio de filas en la tabla de enrutamiento. Se tarda casi diez segundos en calcularlo. Con 20k filas, lleva casi tres segundos. Necesito Shooting Star porque necesito las restricciones de giro.

Aquí hay algunas ideas que estoy tratando de implementar:

  • En el SQL donde pgRouting obtiene las formas, use un st_buffer para que no obtenga todas las formas, sino solo las formas "cercanas":

    seleccione * de shortest_path_shooting_star ('SELECCIONAR ruta. * DESDE ruta de ruta, (seleccione st_buffer (st_envelope (st_collect (geometry)), 4) como geometría de ruta donde id =' || source_ || 'or id =' || target | | ') e DONDE rout.geometry && e.geometry', fuente, destino, verdadero, verdadero);

Mejoró el rendimiento, pero si el camino necesita salir del búfer, puede devolver un error de "no se encontró ruta", entonces ... ¿gran búfer? varias llamadas aumentando el búfer hasta que encuentre un camino?

  • Rutas rápidas en caché

Como sugirió dassouki, guardaré en caché algunas rutas "útiles" para que, si la distancia es demasiado larga, pueda atravesar estas rutas rápidas y solo tenga que encontrar la forma de entrar y salir de ellas.

  • Tabla de particiones por índice gis

Pero supongo que, si va a la memoria, realmente no importa ... Debería probarlo, de todos modos.

Por favor, sigue publicando si encuentras otra idea.

Además, ¿sabe si hay algún pgRouting compilado para Postgres9?


+1 Parece que hay algunas ideas útiles y constructivas aquí. Tenga en cuenta que si desea que se respondan sus preguntas, es mejor formularlas como una nueva pregunta. Nuestras preguntas frecuentes le indicarán cómo proceder.
whuber

Délawen, también he estado pensando en tu primera idea (ST_Buffer) y preveo el mismo problema. Sin embargo, la ventaja podría ser de 2 maneras: el conjunto de datos es más pequeño y, por lo tanto, más rápido y, a medida que se realiza más procesamiento en Postgresql, tiene formas de optimizarlo nuevamente. Atm estoy usando Ubuntu 11 donde postgresql 8.4 es la última versión.
mrg

mrg, compilé pgRouting en un Ubuntu Maverick para PostgreSQL 9.0 sin mucho problema. Postgis para PostgreSQL 9.0 se puede encontrar aquí: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main amd64 Paquetes
Délawen

Se me ocurrieron 2 ideas. 1) Una combinación de 'rutas rápidas en caché' y 'st_buffer'. De esa manera, usted garantiza encontrar una ruta y no todas las personas se verán obligadas a seguir la misma ruta. 2) Solo use postgis para llenar un gráfico estático (con Boost (C), nx_spatial (Python), neo4j (Java), etc.) y reutilice ese gráfico para cada consulta de búsqueda.
mrg

¿Qué pasa con reducir el costo (es decir, aumentar la preferencia) para bordes 'rápidos' como carreteras cuando la distancia entre el inicio y el final es mayor que un umbral? El factor de impulso también podría estar relacionado con la distancia: más grande para distancias más largas, más pequeño para más corto.
unicoletti

5

Acabamos de crear una rama en git para una ruta más corta restringida a su vez @ https://github.com/pgRouting/pgrouting/tree/trsp

Lo siento, todavía no hay documentación, pero si haces preguntas en la lista de pgRouting, salgo y responderé. Este código se ejecuta mucho más rápido que la estrella fugaz y se basa en el algoritmo Dijkstra.

-Steve


0

Tengo una tabla de ruta de origen que contiene ~ 1200000 bordes. En mi i7 con SSD, se necesitan 12 segundos para crear una ruta. Mi idea para aumentar el rendimiento es dividir la tabla de borde en varias tablas de nivel de zoom. Me refiero al nivel que es idéntico al de google tiles. En el octavo nivel de zoom, por ejemplo, tengo 88 tablas. Cada tabla contiene un subconjunto de carreteras y sus áreas se superponen entre sí para calcular una ruta entre dos puntos que se encuentran a una distancia no mayor de 290 km. En el noveno nivel, el tiempo de cálculo cae a 0.25 segundos y tenemos 352 tablas. La recreación de todos los gráficos en caso de que editemos carreteras no lleva más de una hora. La forma radical de aumentar la velocidad de enrutamiento es utilizar el algoritmo Floyd-Warshall. Pero nadie sabe cuánto se tarda en calcular la matriz predecesora en tantos bordes.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.