Como otimizar o pgrouting para obter velocidade?

22

Estou usando o pgrouting em um banco de dados postgis criado por meio do osm2pgrouting. Ele executa muito bem em um conjunto de dados limitado (3,5 mil maneiras, todo o caminho mais curto A * pesquisa <20 ms).

No entanto, desde que importei uma caixa delimitadora maior (122k maneiras) da europe.osm, o desempenho caiu muito (um caminho mais curto custa cerca de 900ms).

Eu acho que usando A * a maioria dessas bordas nunca será visitada, pois estão fora do caminho.

O que fiz até agora na tentativa de melhorar a velocidade:

  • Coloque um índice na coluna de geometria (sem efeito perceptível)
  • Aumentei minha memória de 8GB para 16GB
  • Altere as configurações de memória do postgresql (shared_buffers, effective_cache_size) de (128MB, 128MB) para (1GB, 2GB) (sem efeito perceptível)

Tenho a sensação de que a maior parte do trabalho está sendo feita na biblioteca C Boost, onde o gráfico está sendo feito, para otimizar o postgresql não me dará resultados muito melhores. Como faço pequenas alterações no conjunto de linhas que seleciono para A * em todas as pesquisas, tenho um pouco de medo de que a biblioteca de impulso não consiga armazenar em cache meu gráfico e precise reconstruir todas as arestas de 122k todas as vezes (mesmo que use apenas uma subconjunto limitado a cada consulta). E não tenho ideia de quanto é gasto fazendo isso em comparação com a pesquisa de caminho mais curta real.

Algum de vocês usa pgrouting em um conjunto de dados OSM 122k ou superior? Que desempenho devo esperar? Quais configurações afetam mais o desempenho?

mrg
fonte
2
Não sou especialista em pgrouting, mas você pode armazenar em cache os resultados, por exemplo, se você souber que uma sub-rota comum é sempre usada, pode precachá-la? portanto, você precisa fazer menos pesquisas? Além disso, você limita buscas a artigos e colecionadores?
dassouki
1
Eu permito pesquisa gratuita em caixas eletrônicos, então acho que não posso assumir muito por sub-rotas. Também estou armazenando em cache o resultado das pesquisas dos últimos x minutos, mas isso não me ajuda a novas pesquisas. Tenho a sensação de que A * nesse tamanho ainda deve ser muito rápido, desde que eu possa manter o gráfico inteiro estático na memória. Deve haver pessoas que encaminham esse caminho para um país inteiro que sabem como melhorar o desempenho.
Mrg
1
Outra opção seria construir uma matriz O / D (matriz de origem / destino). Essa é uma técnica que usamos na engenharia de tráfego. divida a rede em zonas, digamos que uma cidade grande possa ter 100 zonas. Cada zona teria um centróide fictício. Conecte o centróide à sua rede através de um link fictício. Em seguida, você pode remodelar toda a sua rede em 100 x 100 viagens (10.000 viagens no total). Quando um usuário faz uma pesquisa, o pgrouting precisa encontrar uma rota fechada para o link centróide ou fictício no lado de origem e destino.
dassouki
2
Você não obtém resultados estranhos se alguém quiser ir de uma zona para a outra, mas é roteado pelos centróides? Ou você só usa isso quando as zonas estão mais afastadas? Sua solução faz mais sentido se os clientes quiserem ir mais rápido de A a B, mas, no meu caso, eu tenho que lidar com clientes que desejam caminhar, pedalar etc. para lazer e gostaria de escolher rotas únicas e não ser forçado a ir através da rota padrão.
mrg
3
Se você está procurando uma solução multimodal (bicicleta, caminhada, transporte público, passeio), deve realmente dar uma olhada no site de roteamento multimodal TriMet de Portland, Oregon, que usa o OpenTripPlanner: trimet.org/news/releases/oct15-rtp. htm
RyanDalton 15/11

Respostas:

10

Quando confrontado com tarefas como essa, seu objetivo principal é ser racional. Não mude os parâmetros com base no "pressentimento". Embora o intestino pareça funcionar para Hollywood, não para nós que moramos no mundo real. Bem, pelo menos não meu instinto ;-).

Você deve:

  1. estabeleça uma métrica utilizável e repetível (como o tempo necessário para uma consulta de pgrouting)

  2. salve os resultados das métricas em uma planilha e faça a média deles (descarte o melhor e o pior). Isso informará se as alterações que você está fazendo estão indo na direção certa

  3. monitore seu servidor usando top e vmstat (supondo que você esteja no * nix) enquanto as consultas estão em execução e procure por padrões significativos: lotes de io, alta cpu, troca, etc. Se a cpu estiver esperando por E / S, tente melhorar desempenho do disco (isso deve ser fácil, veja abaixo). Se a CPU estiver 100% sem nenhuma atividade significativa do disco, você precisará encontrar uma maneira de melhorar a consulta (isso provavelmente será mais difícil).

Por uma questão de simplicidade, presumo que a rede não esteja desempenhando nenhum papel significativo aqui.

Melhorando o desempenho do banco de dados

Atualize para a versão mais recente do Postgres. A versão 9 é muito melhor que as versões anteriores. É grátis, então você não tem motivos para não.

Leia o livro que eu já recomendei aqui .

Você realmente deveria ler. Eu acredito que os capítulos relevantes para este caso são 5,6,10,11

Melhorando o desempenho do disco

  1. Obtenha uma unidade SSD e coloque todo o banco de dados nela. O desempenho de leitura provavelmente quadruplicará e o desempenho de gravação também deve melhorar radicalmente

  2. atribua mais memória ao postgres. Idealmente, você deve poder atribuir memória suficiente para que todo (ou a parte mais quente) possa ser armazenado em cache na memória, mas não muito para que ocorra a troca. Trocar é muito ruim. Isso é coberto no livro citado no parágrafo anterior

  3. desativar atime em todos os discos (adicione as opções de noatime ao fstab)

Melhorando o desempenho da consulta

Use as ferramentas descritas no livro citado acima para rastrear suas consultas e encontrar paradas que valem a pena otimizar.

Atualizar

Após os comentários, observei o código-fonte do procedimento armazenado

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

e parece que depois que a consulta foi ajustada, não há muito mais espaço para melhorias, pois o algoritmo é executado completamente na memória (e, infelizmente, em apenas um processador). Receio que sua única solução seja encontrar um algoritmo melhor / mais rápido ou um que possa executar multithread e depois integrá-lo ao postgres, criando uma biblioteca como pgrouting ou usando algum middleware para recuperar os dados (e armazená-los em cache, talvez) e alimente-o com o algoritmo.

HTH

unicoletti
fonte
Eu li partes do livro que você recomenda. Meu conjunto de dados ainda é pequeno o suficiente para caber inteiramente na memória; portanto, acho que o desempenho do disco não deve ser um gargalo (vou verificar melhor meus recursos ao testar para confirmar isso). Eu acho que o Postgresql só entra em jogo no processo de pgrouting quando ele faz uma simples seleção * da tabela para alimentar a biblioteca C Boost com linhas / tuplas para realizar a pesquisa real ((alguém pode confirmar isso), então eu temo que não haja muito a ganhar em si Postgresql sua resposta parece muito bom para o desempenho Postgresql mas talvez não para pgrouting desempenho específico..
MRG
@mrg Eu realmente pensei nisso, mas eu queria ter certeza de que você não deixaria de fora as frutas mais baixas. Pensando nisso, você passou de 20ms para 3,5k a 900ms para 122k, o que, imho, não é totalmente ruim. Boa sorte
unicoletti
Solid State Drives fazer aumentar o desempenho (velocidade semelhante ao que caching)
Mapperz
Na minha experiência, se estiver usando pgrouting em todos os conjuntos de dados (tabela), não haverá grandes benefícios com o mecanismo do Postgres. O índice nem é usado, portanto é inútil. Em toda consulta, a tabela inteira é carregada na memória. buffers e caches compartilhados também não deram nenhum benefício de desempenho, porque cada consulta carrega toda a tabela na memória. Se alguém conseguir reutilizar os dados carregados na memória para consultas subsequentes, informe-nos. Somente o possível aumento de desempenho que vejo nas unidades SDD, mas nunca o testei. Mais memória permite apenas consultas mais concorrentes, não desempenho.
Mario Miler
8

Eu tenho o mesmo problema e estava prestes a perguntar em listas de discussão, então obrigado a todos!

Estou usando o Shooting Star com um milhão e meio de linhas na tabela de roteamento. Demora quase dez segundos para calcular. Com 20k linhas, leva quase três segundos. Preciso de Shooting Star porque preciso das restrições de turno.

Aqui estão algumas idéias que estou tentando implementar:

  • No SQL em que o pgRouting obtém os caminhos, use um st_buffer para que não obtenha todos os caminhos, mas apenas os caminhos "próximos":

    selecione * de shortest_path_shooting_star ('SELECT rout. * FROM roteamento de roteamento, (selecione st_buffer (st_envelope (st_collect (geometry)), 4) como geometria do roteamento onde id =' || source_ || 'ou id =' || target | | ') e ONDE rout.geometry && e.geometry', origem, destino, verdadeiro, verdadeiro);

Melhorou o desempenho, mas se o caminho precisar sair do buffer, ele pode retornar um erro "nenhum caminho encontrado", então ... buffer grande? várias chamadas aumentando o buffer até encontrar um caminho?

  • Rotas rápidas armazenadas em cache

Como sugerido por dassouki, armazenarei em cache algumas rotas "úteis"; portanto, se a distância for muito longa, ela poderá percorrer essas rotas rápidas e apenas precisar encontrar a maneira de entrar e sair delas.

  • Tabela de partição por índice gis

Mas suponho que, se for para a memória, realmente não importa ... Deveria testá-lo, de qualquer maneira.

Por favor, continue postando se você encontrar outra idéia.

Além disso, você sabe se existe algum pgRouting compilado para o Postgres9?

Délawen
fonte
+1 Parece haver algumas idéias úteis e construtivas aqui. Observe que, se você deseja que suas perguntas sejam respondidas, é melhor formulá-las como uma nova pergunta. Nosso FAQ lhe dirá como proceder.
whuber
Délawen, eu também estive pensando em sua primeira ideia (ST_Buffer) e prevejo o mesmo problema. A vantagem, no entanto, pode ser de duas maneiras: o conjunto de dados é menor e, portanto, mais rápido e, à medida que mais processamento é feito no Postgresql, você tem maneiras de otimizá-lo novamente. Atm estou usando o Ubuntu 11, em que o postgresql 8.4 é a versão mais recente.
mrg
mrg, compilei o pgRouting em um Ubuntu Maverick para PostgreSQL 9.0 sem muito problema. O Postgis para PostgreSQL 9.0 pode ser encontrado aqui: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main amd64 Packages
Délawen
Eu vim com 2 idéias. 1) Uma combinação de 'rotas rápidas armazenadas em cache' e 'st_buffer'. Dessa forma, você garante encontrar uma rota e as pessoas não serão todas forçadas na mesma rota. 2) Use apenas o postgis para preencher um gráfico estático (com Boost (C), nx_spatial (Python), neo4j (Java), etc) e reutilize esse gráfico para todas as consultas de pesquisa.
Mrg
E quanto a diminuir o custo (ou seja, aumentar a preferência) para arestas 'rápidas' como rodovias quando a distância entre o início e o final é maior que um limite? O fator de impulso também pode estar relacionado à distância: maior para distâncias maiores, menor para menores.
Unicoletti
5

Acabamos de criar uma ramificação no git para um caminho mais curto restrito por vez @ https://github.com/pgRouting/pgrouting/tree/trsp

Desculpe, ainda não há documentação, mas, se você fizer perguntas na lista pgRouting, eu saio lá e responderei. Esse código é executado muito mais rápido que uma estrela cadente e é baseado no algoritmo Dijkstra.

-Steve

Stephen Woodbridge
fonte
0

Eu tenho uma tabela de rota de origem que contém ~ 1200000 bordas. No meu i7 com SSD, são necessários 12 segundos para criar uma rota. Minha ideia para aumentar o desempenho é dividir a tabela de borda em várias tabelas de nível de zoom. Quero dizer, o nível idêntico ao google tiles. No 8º nível de zoom, por exemplo, tenho 88 tabelas. Cada tabela contém um subconjunto de estradas e suas áreas se sobrepõem, de modo a calcular uma rota entre dois pontos que ficam a menos de 290 km de distância e leva 2 segundos. No 9º nível, o tempo de cálculo cai para 0,25 s e temos 352 tabelas. A recriação de todos os gráficos, caso editemos estradas, não leva mais de uma hora. A maneira radical de aumentar a velocidade do roteamento é usar o algoritmo de Floyd-Warshall. Mas ninguém sabe quanto é necessário para calcular a matriz predecessora em tantas arestas.

Vadym
fonte