Hızlandırmayı nasıl hızlandırabilirim?


22

Osm2pgrouting ile oluşturulan bir postgis veritabanı üzerinde pgrouting kullanıyorum. Sınırlı bir veri kümesinde çok iyi performans gösterir (3.5k yolu, tümü kısa A * araması <20 msn).

Ancak europe.osm'den daha büyük bir sınırlama kutusu (122k yol) ithal ettiğimden bu yana performans çok azaldı (en kısa yol 900ms civarında).

A * 'yı kullanmanın, bu kenarların çoğunun eskiden olduğu gibi hiçbir zaman ziyaret edilmeyeceğini düşünüyorum.

Hızı arttırmak için şu ana kadar neler yaptım:

  • Geometri sütununa bir dizin koyun (fark edilebilir bir etki yok)
  • Hafızamı 8GB'tan 16GB'a çıkardım
  • Postgresql hafıza ayarlarını (shared_buffers, effect_cache_size) (128MB, 128MB) 'den (1GB, 2GB)' a (fark edilebilir efekt yok) değiştirin

Çalışmanın çoğunun grafiğin yapıldığı C Boost kütüphanesinde yapıldığı hissine sahibim, böylece postgresql'i optimize etmek bana çok daha iyi sonuçlar vermeyecek. Her arama için A * için seçtiğim satır kümesinde küçük değişiklikler yaptığım için, artırma kütüphanesinin grafiğimi önbelleğe alamaması ve her seferinde tüm 122k kenarlarını yeniden oluşturması gerektiğinden korkuyorum (yalnızca Her sorgu sınırlı altküme). Ve bunun için en kısa yol araştırmasına göre ne kadar harcandığını bilmiyorum.

Herhangi biriniz 122k veya daha büyük bir OSM veri setinde pgrouting kullanıyor mu? Hangi performansı beklemeliyim? Hangi ayarlar performansı en çok etkiler?


2
Ben bir serdarma uzmanı değilim, ama sonuçları önbelleğe alabilir misiniz, örneğin, ortak bir alt yolun her zaman kullanıldığını biliyorsanız, önizleyebilir misiniz? bu yüzden daha az arama yapmak zorunda mısın? Ayrıca, aramaları Arterlere ve koleksiyonerlere sınırladığın için mi?
dassouki

1
Ücretsiz arama atm izin veririm, bu yüzden alt yollar için çok fazla varsayabileceğimi sanmıyorum. Ayrıca, son x dakikadaki aramaların sonucunu önbelleğe alıyorum, ancak bu yeni aramalar için bana yardımcı olmuyor. Grafiğin tamamını bellekte sabit tutabildiğim sürece, bu boyuttaki A * değerinin gerçekten hızlı olması gerektiğini hissediyorum. Performansı nasıl artıracağını bilen bütün bir ülkede bu yoldan geçen insanlar olmalı.
mrg

1
Diğer bir seçenek ise bir O / D matrisi (başlangıç ​​/ varış matrisi) oluşturmaktır. Bu, trafik mühendisliğinde kullandığımız bir tekniktir. ağı bölgelere ayırın, böylece büyük bir kentin 100 bölgeye sahip olabileceğini varsayalım. Her bölgenin sahte bir sentroidi olurdu. Sahte bir bağlantı üzerinden centroid'i ağınıza bağlayın. Ardından, tüm ağınızı 100 x 100 seyahat (toplam 10.000 seyahat) olarak yeniden düzenleyebilirsiniz. Bir kullanıcı bir arama yaptığında, parolanın merkeze veya hedef tarafa merkeze ya da yapay bağlantıya kapalı bir yol bulması gerekir.
dassouki

2
Birisi bir bölgeden diğerine geçmek isterse, ancak merkezlerinden yönlendirilip, garip sonuçlar almaz mısın? Yoksa bunu sadece bölgeler daha uzaktayken mi kullanıyorsunuz? Müşterileriniz A'dan B'ye en hızlı şekilde ulaşmak isterse çözümünüz en mantıklı olanıdır, ancak benim durumumda boş zamanlarında yürümek, bisiklete binmek, vb. Gitmek isteyen ve benzersiz yollar seçmek isteyen ve gitmeye zorlanan müşterilerle uğraşmak zorundayım. standart yoldan.
mrg

3
Multimodal bir çözüm arıyorsanız (bisiklet, yürüyüş, toplu taşıma, sürücü), Oregon, OpenTripPlanner kullanan TriMet multimodal rotalama sitesi Portland'a gerçekten göz atmalısınız: trimet.org/news/releases/oct15-rtp. htm
RyanDalton

Yanıtlar:


10

Bunun gibi görevlerle karşılaştığınızda birincil amacınız rasyonel olmaktır. 'Bağırsak duygusuna' dayanan paraşütleri değiştirmeyin. Bağırsak Hollywood için çalışıyor gibi gözükse de, gerçek dünyada yaşayan bizler için değil. En azından benim bağırsaklarım ;-).

Malısın:

  1. kullanılabilir ve tekrarlanabilir bir metrik oluşturmak (bir sorgulama sorgusu için gereken zaman gibi)

  2. metrik sonuçlarını bir e-tabloya kaydedin ve ortalamalarını alın (en iyi ve en kötü şekilde atın). Bu, yaptığınız değişikliklerin doğru yöne gidip gitmediğini size söyleyecektir.

  3. Sorgular çalışırken üst ve vmstat kullanarak (nix * 'in üzerinde olduğunu varsayarak) sunucunuzu izleyin ve önemli kalıpları arayın: çok fazla io, yüksek cpu, takas, vb. disk performansı (bu kolay olmalı, aşağıya bakınız). Eğer CPU, herhangi bir önemli disk etkinliği olmadan% 100 ise, sorguyu iyileştirmenin bir yolunu bulmanız gerekir (bu muhtemelen daha zor olacaktır).

Sadelik uğruna, ağın burada önemli bir rol oynamadığını farz ediyorum.

Veri tabanı performansını iyileştirme

En son Postgres sürümüne yükseltin. Sürüm 9, önceki sürümlerden çok daha iyidir. Ücretsiz olduğu için, yapmamanız için hiçbir neden yok.

Zaten burada tavsiye ettiğim kitabı oku .

Gerçekten okumalısın. Bu dava için ilgili bölümlerin 5,6,10,11 olduğuna inanıyorum.

Disk performansını iyileştirme

  1. Bir SSD sürücüsü edinin ve tüm veritabanını üzerine yerleştirin. Okuma performansı büyük olasılıkla dört katına çıkacak ve yazma performansı da radikal bir şekilde artacaktır

  2. postgreslere daha fazla hafıza verin. İdeal olarak, (veya en sıcak kısım) bütününün belleğe önbelleğe alınabilmesi için yeterli bellek atamanız gerekir, ancak takas işlemi gerçekleşmesi için çok fazla değil. Değişim çok kötü. Bu, önceki paragrafta belirtilen kitapta ele alınmıştır.

  3. tüm disklerde atime işlevini devre dışı bırak ( öğleden sonra seçeneklerini fstab'a ekle )

Sorgu performansının iyileştirilmesi

Sorgunuzu / izlerinizi takip etmek ve optimize edilmeye değer durakları bulmak için yukarıda belirtilen kitapta açıklanan araçları kullanın.

Güncelleştirme

Yorumlardan sonra saklı yordamın kaynak koduna baktım.

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

ve sorgu ayarlandıktan sonra, algoritma tamamen bellekte çalıştığı için (ve ne yazık ki sadece bir cpu üzerinde) geliştirmeye daha fazla yer kalmayacak gibi görünüyor. Korkarım ki tek çözümünüz, daha iyi / daha hızlı bir algoritma bulmak veya çok iş parçacıklı çalışabilen ve daha sonra verileri almak için bazı ara katman yazılımları kullanarak (ve belki önbelleğe alma) ya da peguting gibi bir kütüphane oluşturarak onu postgreslerle bütünleştirmektir. algoritmaya göre besleyin.

HTH


Tavsiye ettiğin kitabın bölümlerini okudum. Veri setim hala tamamen belleğe sığacak kadar küçük, bu nedenle disk performansının bir darboğaz olmaması gerektiğini düşünüyorum (bunu onaylamak için test ederken kaynaklarımı daha iyi kontrol edeceğim). Postgresql, yalnızca tablodan C Boost kütüphanesini satır / tuplarla beslemek için basit bir seçim * yapması durumunda (bu biri bunu onaylayabilir) bu yüzden korkmadığı için, yalnızca çoğaltma işleminde devreye giriyor. çok Postgresql kendisi kazanmak için Yanıtınız belirli performans pgrouting için Postgresql performans için çok iyi görünüyor ama belki o kadar..
MRG

@mrg Aslında bunu düşünmüştüm, fakat alçaktan meyveyi dışarıda bırakmadığınızdan emin olmak istedim. Bunu düşünmek, 3.5k için 20ms'den, 122k için 900ms'e, yani tamamen kötü değil. İyi şanslar
unicoletti 15:11

Katı Hal Sürücüleri performansı arttırır (önbelleğe alma hızına benzer hızlarda)
Mapperz

Deneyimlerime göre, tüm veri kümelerinde (tablo) pgrouting kullanıyorsanız, o zaman Postgres motorundan büyük bir faydası olmaz. Endeks bile kullanılmıyor, bu yüzden işe yaramaz. Her sorguda tüm tablo hafızaya yüklenir. paylaşılan tamponlar ve önbellekleri de herhangi bir performans avantajı vermedi çünkü her sorgu tüm tabloyu belleğe yüklüyor. Birisi daha sonraki sorgular için yüklenen verileri bellekte tekrar kullanmayı başardıysa, lütfen bize bildirin. Yalnızca olası performans artışı SDD sürücülerinde görüyorum, ancak hiç test etmedim. Daha fazla bellek, yalnızca eşzamanlı sorgulara izin verir, performansa değil.
Mario Miler,

8

Ben de aynı sorunu yaşıyorum ve e-posta listelerinde sormak üzereydim, herkese teşekkürler!

Ben kullanıyorum Shooting Star yönlendirme masaya milyonlarca buçuk satırlarla. Hesaplaması neredeyse on saniye sürüyor. 20k satır ile neredeyse üç saniye sürer. Shooting Star'a ihtiyacım var çünkü dönüş kısıtlamalarına ihtiyacım var.

İşte uygulamaya çalıştığım bazı fikirler:

  • PgRouting uygulamasının yollarını bulduğu SQL'de, bir st_buffer kullanın , böylece tüm yolları almaz, sadece "yakındaki" yolları kullanır:

    shortest_path_shooting_star'dan * 'ı seçin (' SELECT rout. * FRUT rout routu, (st_buffer (st_envelope (st_collect (geometry))), 4) rotadan geometri olarak seçin (id = '|| source_ ||' veya id = '|| target | | ') e NEREDE rout.geometri && e.geometri', kaynak, hedef, doğru, doğru);

Performansı arttırdı, ancak yolun arabellek dışına çıkması gerekiyorsa, "yol bulunamadı" hatası verebilir, yani ... büyük arabellek? Birkaç aramalar arabellek bir yol bulana kadar arttırıyor?

  • Hızlı rotalar önbelleğe alınır

Dabiouki'nin önerdiği gibi, bazı "faydalı" rotaları önbelleğe alacağım, bu nedenle eğer mesafe çok uzunsa, bu hızlı rotalardan geçebilir ve bunların içine girip çıkabilmeleri gerekir.

  • Gis indeksine göre bölme tablosu

Ama sanırım, eğer hafızaya giderse, gerçekten önemli değil ... Yine de test etmeli.

Lütfen başka bir fikir bulursanız göndermeye devam edin.

Ayrıca, Postgres9 için bazı derlenmiş pgRouting olup olmadığını biliyor musunuz?


+1 Burada bazı faydalı ve yapıcı fikirler var. Lütfen, sorularınızın cevaplandırılmasını istiyorsanız, bunları yeni bir soru olarak formüle etmenin en iyisi olduğunu unutmayın. Bizim SSS nasıl devam etmek söyleyecektir.
whuber

Ayrıca, ilk fikrin hakkında da düşündüm (ST_Buffer) ve aynı sorunu öngörüyorum. Ancak bu avantaj 2 yollu olabilir: veri kümesi daha küçük ve dolayısıyla daha hızlıdır ve işlemlerin çoğu Postgresql'de yapıldığı için, tekrar optimize etmenin yollarına sahipsiniz. Atm Ubuntu 11 kullanıyorum, burada postgresql 8.4 en son sürümdür.
mrg

mrg, PostgreSQL 9.0 için bir Ubuntu Maverick üzerinde pgRouting'i çok fazla derlemeden derledim. PostgreSQL 9.0 için Postgis'i burada bulabilirsiniz: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main amd64 Paketler
Délawen

2 fikir buldum. 1) 'Hızlı yollar önbelleğe alınmış' ve 'st_buffer' kombinasyonu. Bu şekilde bir rota bulmayı garanti ediyorsunuz ve insanlar aynı rotaya zorlanmayacak. 2) Sadece bir statik grafiği (Boost (C), nx_spatial (Python), neo4j (Java), vb.) İle doldurmak için postgis kullanın ve bu grafiği her arama sorgusu için yeniden kullanın.
mrg

Başlangıç ​​ve bitiş arasındaki mesafenin bir eşikten büyük olması durumunda, otoyollar gibi 'hızlı' kenarlar için maliyetin düşürülmesi (yani, tercihin artırılması)? Yükseltme faktörü ayrıca mesafeyle ilgili olabilir: daha uzun mesafeler için daha büyük, daha kısa için daha küçük.
unicoletti

5

Git dönüşünde kısıtlı en kısa yol için bir şube oluşturduk @ https://github.com/pgRouting/pgrouting/tree/trsp

Üzgünüz, henüz bir belge yok, ancak pgRouting listesine sorular sorarsanız, orada takılıyorum ve yanıt vereceğim. Bu kod, kayan yıldızdan çok daha hızlı çalışır ve Dijkstra algoritmasına dayanır.

-Steve


0

~ 1200000 kenar içeren bir kaynak yol tablosu var. SSD'li i7 cihazımda bir rota oluşturmak 12 saniye sürüyor. Performansı arttırma fikrim, kenar tablosunu birkaç yakınlaştırma seviyesi tablosuna bölmektir. Ben google fayans aynı seviyesini demek. Sekizinci zoom seviyesinde, örneğin, 88 tablom var. Her tablo bir yol alt kümesini içerir ve alanları birbirinden örtüşür, böylece birbirinden 290 km'den daha uzak olmayan iki nokta arasındaki bir rotayı hesaplamak 2 saniye sürer. 9. seviyede hesaplamalar 0.25 saniyeye düşer ve 352 tablomuz vardır. Yolları düzenlediğimiz takdirde tüm grafiklerin yeniden oluşturulması bir saatten fazla sürmez. Yönlendirme hızını arttırmanın radikal yolu Floyd-Warshall algoritmasını kullanmak. Ancak hiç kimse önceki matrisi bu kadar çok kenarda hesaplamanın ne kadar gerekli olduğunu bilmiyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.