注入速度を最適化するにはどうすればよいですか?


22

osm2pgroutingで作成されたpostgisデータベースでpgroutingを使用しています。限られたデータセットで非常に優れたパフォーマンスを発揮します(3.5kの方法、20ミリ秒未満のすべての最短パスA *検索)。

ただし、europe.osmからより大きなバウンディングボックス(122kウェイ)をインポートしたため、パフォーマンスが大幅に低下しました(最短パスのコストは約900ミリ秒)。

A *を使用すると、これらのエッジのほとんどは、邪魔にならないため、決してアクセスされないと思います。

速度を改善するためにこれまでに行ったこと:

  • ジオメトリ列にインデックスを配置します(顕著な効果はありません)
  • メモリーを8GBから16GBに増やしました
  • postgresqlのメモリ設定(shared_buffers、effective_cache_size)を(128MB、128MB)から(1GB、2GB)に変更します(顕著な効果はありません)

ほとんどの作業はグラフが作成されているC Boostライブラリで行われているので、postgresqlを最適化しても良い結果が得られないと感じています。検索ごとにA *に選択した行のセットに小さな変更を加えると、ブーストライブラリはグラフをキャッシュできず、毎回122kのエッジをすべて再構築する必要があるのではないかと心配しています(非常にクエリごとの限定サブセット)。そして、実際の最短パス検索と比較して、それを行うのにどれだけの費用がかかるかわかりません。

122k以上のOSMデータセットでpgroutingを使用している人はいますか?どのようなパフォーマンスが期待できますか?どの設定がパフォーマンスに最も影響しますか?


2
私はプラウティングの専門家ではありませんが、結果をキャッシュできますか。たとえば、共通のサブルートが常に使用されていることがわかっている場合、事前にキャッシュできますか。したがって、検索を少なくする必要がありますか?また、バンは検索を動脈とコレクターに限定しますか?
dassouki

1
私は無料の検索ATMを許可しているので、サブルートに多くを想定できるとは思いません。また、最後のx分間の検索結果をキャッシュしていますが、それでも新しい検索には役立ちません。グラフ全体をメモリに静的に保持できる限り、このサイズのA *は本当に高速であると感じています。パフォーマンスを改善する方法を知っている全国にこの方法でルーティングする人がいるに違いありません。
MRG

1
別のオプションは、O / Dマトリックス(起点/宛先マトリックス)を作成することです。これは、トラフィックエンジニアリングで使用する手法です。ネットワークをゾーンに分割します。つまり、大都市には100のゾーンがあるとしましょう。各ゾーンにはダミーの重心があります。ダミーリンクを介して重心をネットワークに接続します。その後、ネットワーク全体を100 x 100トリップ(合計10,000トリップ)に改造できます。ユーザーが検索を行うと、pgroutingは、起点側と終点側の重心またはダミーリンクに近いルートを見つける必要があります。
dassouki

2
誰かが1つのゾーンから次のゾーンに移動したいが、重心を経由する場合、奇妙な結果になりませんか?または、ゾーンがさらに離れている場合にのみこれを使用しますか?顧客がAからBまで最速で行きたい場合、あなたのソリューションは最も理にかなっていますが、私の場合、私は余暇のために歩き、自転車などを望み、ユニークなルートを選んで行きたくない顧客に対処しなければなりません標準ルート経由。
mrg

3
マルチモーダルソリューション(自転車、徒歩、公共交通機関、ドライブ)を探している場合は、OpenTripPlannerを使用するオレゴンのTriMetマルチモーダルルーティングサイトであるPortlandを実際に見てください。trimet.org/ news /
RyanDalton

回答:


10

このようなタスクに直面するとき、あなたの主な目的は合理的であることです。「直感」に基づいてパラメータを変更しないでください。腸はハリウッドで機能するように見えますが、現実の世界に住んでいる私たちにとっては機能しません。まあ、少なくとも私の腸ではない;-)。

あなたがすべき:

  1. 使用可能で反復可能なメトリックを確立します(pgroutingクエリに必要な時間など)

  2. メトリックの結果をスプレッドシートに保存し、それらを平均します(最高と最低を破棄します)。これにより、行っている変更が正しい方向に進んでいるかどうかがわかります

  3. クエリの実行中にtopとvmstatを使用してサーバーを監視し(* nixを使用していると仮定)、重要なパターン(多くのio、高CPU、スワッピングなど)を探します。CPUがI / Oを待機している場合は改善を試みますディスクのパフォーマンス(これは簡単です。以下を参照)。代わりに、CPUが100%であり、ディスクの動作がそれほど大きくない場合、クエリを改善する方法を見つける必要があります(これはおそらく難しくなるでしょう)。

簡単にするために、ここではネットワークが重要な役割を果たしていないと仮定します。

データベースのパフォーマンスの改善

最新のPostgresバージョンにアップグレードします。バージョン9は、以前のバージョンよりもはるかに優れています。無料なので、理由はありません。

ここですでにお勧めした本を読んでください

あなたは本当にそれを読むべきです。このケースに関連する章は5,6,10,11であると思います

ディスクパフォ​​ーマンスの改善

  1. SSDドライブを取得し、データベース全体をその上に配置します。読み取りパフォーマンスはほぼ4倍になり、書き込みパフォーマンスも大幅に向上するはずです。

  2. postgresにより多くのメモリを割り当てます。理想的には、全体(または最もホットな部分)をメモリにキャッシュできるように十分なメモリを割り当てることができますが、スワッピングが発生するほど多くはできません。スワップは非常に悪いです。これは、前の段落で引用した本で説明されています。

  3. すべてのディスクでatimeを無効にします(fstabにnoatimeオプションを追加します)

クエリパフォーマンスの向上

上記の本で説明されているツールを使用して、クエリをトレースし、最適化する価値のあるストップを見つけます。

更新

コメントの後、ストアドプロシージャのソースコードを確認しました。

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

また、クエリが調整されると、アルゴリズムがメモリ内で完全に実行されるため(そして残念ながら1つのCPUのみで)、改善の余地はあまりないようです。あなたの唯一の解決策は、より良い/より速いアルゴリズム、またはマルチスレッドを実行できるアルゴリズムを見つけてから、pgroutingのようなライブラリを作成するか、ミドルウェアを使用してデータを取得する(そしてキャッシュする)ことでpostgresと統合することですそれをアルゴリズムに送ります。

HTH


あなたが推薦する本の一部を読みました。私のデータセットはまだメモリに完全に収まるほど小さいので、ディスクのパフォーマンスがボトルネックになることはないと思います(これを確認するためにテストするときにリソースを確認する方が良いでしょう)。Postgresqlは、実際の検索を実行するために行/タプルをC Boostライブラリに供給するためにテーブルから単純なselect *を実行するときにのみ、注入プロセスで機能すると思います(誰かがこれを確認できます)ので、あなたの答えはPostgresqlのパフォーマンスには非常に良いように見えますが、特定のパフォーマンスを向上させるにはそうではないかもしれません。
mrg

@mrg私は実際にそのことを考えていましたが、私はあなたがぶら下がっている果物を除外していないことを確認したかったです。それを考えると、3.5kの20msから122kの900msになりました。幸運
unicoletti

ソリッドステートドライブはパフォーマンスを向上させます(キャッシュと同様の速度)
マッパーズ

私の経験では、すべてのデータセット(テーブル)でpgroutingを使用する場合、Postgresエンジンから大きな利点はありません。インデックスは使用されないため、役に立たない。すべてのクエリで、テーブル全体がメモリにロードされます。また、共有バッファとキャッシュは、すべてのクエリがすべてのテーブルをメモリにロードするため、パフォーマンス上のメリットはありませんでした。誰かがメモリ内のロードされたデータを後続のクエリで再利用することに成功した場合、教えてください。SDDドライブで見られるパフォーマンスの向上のみが可能ですが、テストしたことがありません。メモリを増やすと、パフォーマンスではなく、より多くの同時クエリが可能になります。
マリオミラー

8

私はちょうど同じ問題を抱えており、メーリングリストで質問しようとしていたので、みんなに感謝します!

シューティングスターを使用していますルーティングテーブルに150万行のをしています。計算には約10秒かかります。20k行では、ほぼ3秒かかります。ターン制限が必要なため、シューティングスターが必要です。

ここに私が実装しようとしているいくつかのアイデアがあります:

  • pgRoutingが方法を取得するSQLでは、st_bufferを使用して、すべての方法を取得せず、「近くの」方法のみを取得します。

    select * from shortest_path_shooting_star( 'SELECT rout。* FROM routing rout、(select st_buffer(st_envelope(st_collect(geometry))、4)from geometry from routing from id =' || source_ || 'or id =' || target | | ')e WHERE rout.geometry && e.geometry'、source、target、true、true);

パフォーマンスは向上しましたが、バッファの外側に移動する必要がある場合、「パスが見つかりません」というエラーが返される可能性があります。いくつかの呼び出しは、方法が見つかるまでバッファを増やしますか?

  • キャッシュされた高速ルート

dassoukiが提案したように、いくつかの「有用な」ルートをキャッシュするので、距離が長すぎる場合、これらの高速ルートを通過でき、それらの内外の道を見つける必要があります。

  • gisインデックスによるパーティションテーブル

しかし、私は、それがメモリに行く場合、それは本当に重要ではないと思う...とにかくそれをテストする必要があります。

別のアイデアを見つけたら投稿してください。

また、Postgres9用にコンパイルされたpgRoutingがあるかどうか知っていますか?


+1ここには、有益で建設的なアイデアがいくつかあるようです。質問に回答してもらいたい場合は、新しい質問として作成することをお勧めします。私たちのよくある質問はどのように進んでする方法を教えてくれます。
whuber

デラウェン、私もあなたの最初のアイデア(ST_Buffer)について考えていて、同じ問題を予見しています。ただし、利点は2つの方法があります。データセットが小さいため、Postgresqlでより多くの処理が行われているため、データセットを最適化する方法があります。Atmは、postgresql 8.4が最新バージョンであるUbuntu 11を使用しています。
mrg

mrg、私はPostgreSQL 9.0用のUbuntu MaverickでpgRoutingを大した問題なくコンパイルしました。PostgreSQLの9.0のためのPostGISはここで見つけることができます:ppa.launchpad.net/pi-deb/gis/ubuntuマーベリック/メインAMD64パッケージ
Délawen

2つのアイデアを思いつきました。1)「キャッシュされた高速ルート」と「st_buffer」の組み合わせ。そうすれば、ルートを見つけることが保証され、すべての人が同じルートを強制されることはありません。2)postgisのみを使用して静的グラフ(Boost(C)、nx_spatial(Python)、neo4j(Java)など)を埋め、すべての検索クエリでそのグラフを再利用します。
MRG

開始地点と終了地点間の距離がしきい値よりも大きい場合に、高速道路のような「高速」エッジのコストを下げる(つまり、優先順位を上げる)のはどうでしょうか。ブースト係数は距離に関連する場合もあります。距離が長いほど大きく、短いほど小さくなります。
unicoletti

5

回転制限された最短パス@ https://github.com/pgRouting/pgrouting/tree/trspの gitにブランチを作成しました

まだドキュメントはありませんが、pgRoutingリストで質問がある場合は、ハングアウトして応答します。このコードは、シューティングスターよりもはるかに高速に実行され、ダイクストラアルゴリズムに基づいています。

-スティーブ


0

〜1200000のエッジを含むソースルートテーブルがあります。SSDを搭載したi7では、ルートを作成するのに12秒かかります。パフォーマンスを向上させるための私の考えは、エッジテーブルをいくつかのズームレベルテーブルに分割することです。Googleタイルと同じレベルを意味します。たとえば、8番目のズームレベルでは、88個のテーブルがあります。各テーブルには道路のサブセットが含まれており、互いに290 km以内にある2つのポイント間のルートを計算するために2秒かかるように、それらのエリアは互いに重なり合っています。9番目のレベルでは、計算時間が0.25秒に低下し、352個のテーブルがあります。道路を編集する場合のすべてのグラフの再作成には1時間もかかりません。ルーティングの速度を上げる根本的な方法は、Floyd-Warshallアルゴリズムを使用することです。しかし、非常に多くのエッジで先行行列を計算するのにどれくらいかかるかは誰にもわかりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.