Come posso ottimizzare il pgrouting per la velocità?


22

Sto usando pgrouting su un database postgis creato tramite osm2pgrouting. Funziona molto bene su un set di dati limitato (3,5k vie, tutte le ricerche A * del percorso più breve <20 ms).

Tuttavia da quando ho importato un box di delimitazione più grande (122k vie) da europe.osm, le prestazioni sono diminuite molto (un percorso più breve costa circa 900ms).

Penserei che usando A * la maggior parte di quei bordi non sarà mai visitata perché sono fuori mano.

Quello che ho fatto finora nel tentativo di migliorare la velocità:

  • Inserisci un indice sulla colonna della geometria (nessun effetto evidente)
  • Aumentata la mia memoria da 8 GB a 16 GB
  • Modifica le impostazioni di memoria di postgresql (shared_buffers, actual_cache_size) da (128 MB, 128 MB) a (1 GB, 2 GB) (nessun effetto evidente)

Ho la sensazione che la maggior parte del lavoro venga svolto nella libreria C Boost, dove il grafico viene creato, quindi l'ottimizzazione di postgresql non mi darà risultati molto migliori. Mentre faccio piccole modifiche all'insieme di righe che seleziono per A * per ogni ricerca, ho un po 'paura che la libreria boost non possa memorizzare nella cache il mio grafico e debba ricostruire tutti i 122k edge ogni volta (anche se utilizzerà solo sottoinsieme limitato ogni query). E non ho idea di quanto viene speso per farlo rispetto all'effettiva ricerca del percorso più breve.

Qualcuno di voi usa pgrouting su un set di dati OSM 122k o superiore? Quali prestazioni dovrei aspettarmi? Quali impostazioni influiscono maggiormente sulle prestazioni?


2
Non sono un esperto di puting, ma puoi memorizzare nella cache i risultati, ad esempio, se sai che viene sempre utilizzata una route secondaria comune, puoi precollegarla? quindi, devi fare meno ricerche? Inoltre, puoi limitare le ricerche a Arteriali e collezionisti?
Dassouki,

1
Autorizzo l'ATM di ricerca gratuita, quindi non credo di poter assumere molto per i percorsi secondari. Inoltre sto memorizzando nella cache il risultato delle ricerche degli ultimi x minuti, ma ciò non mi aiuta per le nuove ricerche. Ho la sensazione che A * su queste dimensioni dovrebbe essere ancora molto veloce finché posso mantenere l'intero grafico statico in memoria. Devono esserci persone che indirizzano in questo modo su un intero paese che sanno come migliorare le prestazioni.
martedì

1
Un'altra opzione sarebbe quella di costruire una matrice O / D (matrice di origine / destinazione). Questa è una tecnica che usiamo nell'ingegneria del traffico. dividere la rete in zone, quindi diciamo che una grande città potrebbe avere 100 zone. Ogni zona avrebbe un centroide fittizio. Connetti il ​​centroide alla tua rete tramite un link fittizio. Quindi puoi rimodellare l'intera rete come 100 x 100 viaggi (10.000 viaggi in totale). Quando un utente esegue una ricerca, pgrouting deve trovare un percorso chiuso al centroide o al link fittizio sul lato di origine e destinazione.
Dassouki,

2
Non ottieni strani risultati se qualcuno vuole passare da una zona all'altra ma viene instradato attraverso i loro centroidi? O lo usi solo quando le zone sono più separate? La tua soluzione ha più senso se i clienti vogliono ottenere più velocemente dalla A alla B, ma nel mio caso devo trattare con i clienti che vogliono camminare, andare in bicicletta, ecc. Per piacere e vorrebbero scegliere percorsi unici e non essere costretti ad andare tramite il percorso standard.
sig.

3
Se stai cercando una soluzione multimodale (bici, a piedi, trasporti pubblici, in auto), dovresti dare un'occhiata a Portland, il sito di routing multimodale TriMet dell'Oregon, che utilizza OpenTripPlanner: trimet.org/news/releases/oct15-rtp. htm
Ryan Dalton,

Risposte:


10

Di fronte a compiti come questo il tuo obiettivo primario è essere razionale. Non modificare i parametri in base al "feeling intestinale". Mentre l'intestino sembra funzionare per Hollywood, non per noi che viviamo nel mondo reale. Beh, almeno non il mio istinto ;-).

Dovresti:

  1. stabilire una metrica utilizzabile e ripetibile (come il tempo richiesto da una query pgrouting)

  2. salva i risultati delle metriche in un foglio di calcolo e calcola la media (scarta il meglio e il peggio). Questo ti dirà se le modifiche che stai facendo stanno andando nella giusta direzione

  3. monitora il tuo server usando top e vmstat (supponendo che tu sia su * nix) mentre le query sono in esecuzione e cerca modelli significativi: molto io, cpu alto, scambio, ecc. Se la cpu è in attesa di I / O, prova a migliorare prestazioni del disco (questo dovrebbe essere facile, vedi sotto). Se la CPU è invece al 100% senza alcuna significativa attitudine al disco, devi trovare un modo per migliorare la query (probabilmente sarà più difficile).

Per semplicità suppongo che la rete non stia svolgendo alcun ruolo significativo qui.

Miglioramento delle prestazioni del database

Esegui l'upgrade all'ultima versione di Postgres. La versione 9 è molto meglio delle versioni precedenti. È gratuito, quindi non hai motivo di non farlo.

Leggi il libro che ho raccomandato già qui .

Dovresti davvero leggerlo. Credo che i capitoli pertinenti per questo caso siano 5,6,10,11

Miglioramento delle prestazioni del disco

  1. Ottieni un'unità SSD e inserisci l'intero database su di essa. Molto probabilmente le prestazioni di lettura quadruplicheranno e anche le prestazioni di scrittura dovrebbero migliorare radicalmente

  2. assegnare più memoria a postgres. Idealmente, dovresti essere in grado di assegnare abbastanza memoria in modo che l'intera (o la parte più calda) possa essere memorizzata nella memoria cache, ma non troppo per consentire lo scambio. Lo scambio è molto male. Questo è trattato nel libro citato nel paragrafo precedente

  3. disabilita atime su tutti i dischi (aggiungi le opzioni noatime a fstab)

Miglioramento delle prestazioni delle query

Usa gli strumenti descritti nel libro sopra citato per rintracciare le tue domande e trovare fermate che vale la pena ottimizzare.

Aggiornare

Dopo i commenti ho esaminato il codice sorgente per la procedura memorizzata

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

e sembra che una volta messa a punto la query non ci sia molto più margine di miglioramento poiché l'algoritmo viene eseguito completamente in memoria (e, sfortunatamente, su una sola CPU). Temo che la tua unica soluzione sia quella di trovare un algoritmo migliore / più veloce o uno che possa essere eseguito in multithreading e quindi integrarlo con Postgres creando una libreria come pgrouting o utilizzando un middleware per recuperare i dati (e cache, forse) e alimentalo all'algoritmo.

HTH


Ho letto parti del libro che mi consigliate. Il mio set di dati è ancora abbastanza piccolo da adattarsi interamente alla memoria, quindi penso che le prestazioni del disco non debbano essere un collo di bottiglia (controllerò meglio le mie risorse durante i test per confermarlo). Penso che Postgresql entri in gioco nel processo di pgrouting solo quando fa una semplice selezione * dalla tabella per alimentare la libreria C Boost con riga / tuple per eseguire la vera ricerca ((qualcuno può confermarlo) quindi temo che non ci sia molto da guadagnare in Postgresql stesso. La tua risposta sembra molto buona per le prestazioni di Postgresql, ma forse non è così per migliorare le prestazioni specifiche.
MR

@mrg In realtà ci avevo pensato, ma volevo essere sicuro che non avessi tralasciato il frutto basso. Pensandoci, sei passato da 20ms per 3,5k a 900ms per 122k, il che non è del tutto negativo. Buona fortuna
unicoletti,

Le unità a stato solido aumentano le prestazioni (velocità simili a quella della cache)
Mapperz

Nella mia esperienza, se si utilizza pgrouting su tutti i set di dati (tabella), il motore Postgres non offre grandi vantaggi. L'indice non viene nemmeno utilizzato, quindi è inutile. Su ogni query l'intera tabella viene caricata in memoria. anche i buffer e le cache condivise non hanno apportato alcun vantaggio in termini di prestazioni poiché ogni query carica tutta la tabella in memoria. Se qualcuno riesce a riutilizzare i dati caricati in memoria per le query successive, informaci. Vedo solo un possibile aumento delle prestazioni nelle unità SDD, ma non l'ho mai testato. Più memoria consente solo più query simultanee, non prestazioni.
Mario Miler,

8

Ho lo stesso problema e stavo per chiedere una mailing list, quindi grazie a tutti!

Sto usando Shooting Star con un milione e mezzo di righe sulla tabella di routing. Ci vogliono quasi dieci secondi per calcolarlo. Con 20k righe ci vogliono quasi tre secondi. Ho bisogno di Shooting Star perché ho bisogno delle restrizioni di turno.

Ecco alcune idee che sto cercando di implementare:

  • Sull'SQL in cui pgRouting trova la strada, usa uno st_buffer in modo che non ottenga tutti i modi, ma solo i modi "vicini":

    seleziona * from shortest_path_shooting_star ('SELECT rout. * FROM rout rout, (seleziona st_buffer (st_envelope (st_collect (geometria)), 4) come geometria dal routing dove id =' || source_ || 'o id =' || target | | ') e DOVE rout.geometry && e.geometry', sorgente, target, true, true);

Ha migliorato le prestazioni, ma se la strada deve uscire dal buffer, può restituire un errore "nessun percorso trovato", quindi ... buffer di grandi dimensioni? diverse chiamate aumentano il buffer fino a quando non trova un modo?

  • Percorsi veloci memorizzati nella cache

Come suggerito da Dassouki, memorizzerò nella cache alcuni percorsi "utili", quindi se la distanza è troppo lunga, può percorrere questi percorsi veloci e deve solo trovare il modo di entrare e uscire.

  • Tabella delle partizioni per indice gis

Ma suppongo che, se va in memoria, non importa davvero ... Dovrebbe provarlo, comunque.

Per favore, continua a postare se trovi un'altra idea.

Inoltre, sai se esiste un pgRouting compilato per Postgres9?


+1 Qui sembrano esserci alcune idee utili e costruttive. Tieni presente che se desideri che le tue domande ricevano una risposta, è meglio formularle come una nuova domanda. Le nostre FAQ ti diranno come procedere.
whuber

Délawen, ho anche pensato alla tua prima idea (ST_Buffer) e ho previsto lo stesso problema. Il vantaggio tuttavia potrebbe essere in 2 modi: il set di dati è più piccolo e quindi più veloce e poiché gran parte dell'elaborazione viene eseguita in Postgresql hai di nuovo modo di ottimizzarlo. Atm sto usando Ubuntu 11 dove postgresql 8.4 è l'ultima versione.
sig.

mrg, ho compilato pgRouting su Ubuntu Maverick per PostgreSQL 9.0 senza troppi problemi. Postgis per PostgreSQL 9.0 può essere trovato qui: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main pacchetti amd64
Délawen

Ho avuto 2 idee. 1) Una combinazione di "percorsi veloci memorizzati nella cache" e "st_buffer". In questo modo garantisci di trovare un percorso e le persone non saranno costrette a seguire lo stesso percorso. 2) Usa Postgis solo per riempire un grafico statico (con Boost (C), nx_spatial (Python), neo4j (Java), ecc.) E riutilizzare quel grafico per ogni query di ricerca.
sig.

Che ne dici di abbassare il costo (es. Aumentare la preferenza) per i bordi "veloci" come le autostrade quando la distanza tra inizio e fine è maggiore di una soglia? Il fattore di spinta potrebbe anche essere correlato alla distanza: più grande per le distanze più lunghe, più piccolo per le brevi.
unicoletti,

5

Abbiamo appena creato un ramo in git per un percorso più breve con accesso limitato @ https://github.com/pgRouting/pgrouting/tree/trsp

Spiacente, non ho ancora la documentazione, ma se fai domande sulla lista pgRouting, esco e rispondo. Questo codice funziona molto più velocemente della stella cadente e si basa sull'algoritmo Dijkstra.

-Steve


0

Ho una tabella di route di origine che contiene ~ 1200000 bordi. Sul mio i7 con SSD ci vogliono 12 secondi per creare una rotta. La mia idea per aumentare le prestazioni è quella di dividere la tabella dei bordi in diverse tabelle dei livelli di zoom. Intendo il livello identico alle tessere di Google. All'ottavo livello di zoom, ad esempio, ho 88 tabelle. Ogni tabella contiene un sottoinsieme di strade e le loro aree si sovrappongono in modo da calcolare un percorso tra due punti che si trovano a non meno di 290 km l'uno dall'altro richiede 2 sec. Al 9 ° livello il tempo di calcolo scende a 0,25 secondi e abbiamo 352 tabelle. La ricreazione di tutti i grafici nel caso in cui modifichiamo le strade non richiede più di un'ora. Il modo radicale per aumentare la velocità di routing è utilizzare l'algoritmo Floyd-Warshall. Ma nessuno sa quanto ci vuole per calcolare la matrice precedente su così tanti bordi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.