ArcGISScriptingおよび大規模な空間データセットのパフォーマンス


38

現在、arcgisscriptingモジュールを使用して、少数のテーブル(合計8つ)で正規化されたかなり大きなデータセット(合計で約10,000レコード)を処理するPythonスクリプトを作成しています。このプロセスは、座標タプル(x、y)に基づいて機能を作成し、他の7つの表にある関係を使用してグラフ(ノードと線)を作成することで構成されます。最終的な出力は、関係を視覚的に表すノードおよびエッジの空間データセットを持つパーソナルジオデータベース(pgdb / fgdb)です。

私の最初の試みは、新しいジオデータベーステーブルとSearchCursorレコードセットのクエリを使用して、発生する多対多のリレーションシップのリンクテーブル(InsertCursor)を作成することでした。15〜20分の処理時間を除いて、これは非常にうまく機能しました。

PythonでcProfilerモジュールを使用すると、検索クエリを実行してリンクテーブルにカーソル(検索カーソルと挿入カーソル)の要求を取り込むときにパーソナルジオデータベースを「スラッシング」すると、パフォーマンスがひどくなります。

少しのリファクタリングで、処理時間を2.5分未満に抑えることができました。トレードオフは、コードでのジオデータベーススキーマの部分的な構築と、すべての関係が照合された後のarcgisscriptingカーソルの要求をInsertCursorsに制限することでした。

私の質問はパフォーマンスです。

  • 大規模なデータセットを扱う際に、合理的な計算時間を維持するために人々が使用したテクニックは何ですか?
  • 最適化の検索で見逃したESRI推奨の方法はありますか?

    特にパーソナルジオデータベースからの場合は、アークギスクリプティングカーソルを作成するときに発生するオーバーヘッドを理解していますが、このサイトとGoogleからパフォーマンスに関連する回答を長時間検索した後、パフォーマンスは人々の努力の最前線ではないという印象を受けています。

  • ESRI製品のユーザーとして、これらのパフォーマンスラグを予想し、容認しますか?

更新

この製品でいくつかの作業を行った後、空間情報を適切な形式からジオデータベースに変換するプロセスを採用した最適化手法のリストを蓄積しました。これは、パーソナルジオデータベースおよびファイルジオデータベース用に開発されました。ちょっとしたこと:

  1. データを読み取り、メモリ内で合理化します。これにより、時間を半分に短縮できます。

  2. メモリ内にフィーチャクラスとテーブルを作成します。フィーチャデータセットキーワーク「in_memory」を使用してメモリをRAMディスクとして使用し、そこで機能を実行してからディスクに書き込みます

  3. ディスクに書き出すには、フィーチャクラスにはCopyFeatureclassを使用し、テーブルにはCopyRowを使用します。

これら3つのことには、100,000以上のフィーチャを30分から30〜40秒にジオデータベースに変換するスクリプトが必要でした。これには、リレーションシップクラスが含まれます。それらは軽く使用されるべきではありません。上記の方法のほとんどは大量のメモリを使用するため、注意を払っていないと問題が発生する可能性があります。


1
別のストレージ形式を使用してみましたか?ファイルジオデータベースはどのように機能しますか?
デレクスイングリー

ファイルジオデータベースのパフォーマンスは、パーソナルジオデータベースよりもわずかに劣ります。昨日、ArcSDEインスタンスの設定と調整に費やして、エンタープライズフォーマットでのパフォーマンスをテストしました。私の調査結果
OptimizePrime

2
これは今では役に立ちませんが、10.1では、Pythonのカーソルのパフォーマンスは、新しいデータアクセスモジュールによって大きな要因(平均的なケースでは桁違いの範囲)によって改善されました。
ジェイソンシャイラー

In_memory用途InMemoryWorkspace edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriDataSourcesGDB/...、任意の数の行、後ScratchWorkspaceFactory(すなわちFileGDB)にすべてをダンプし、すべての作業を行うためにFileGDBに依存している
Ragi Yaserバーフム

回答:


56

この質問はすでに答えられましたが、私は2セントで金を払うことができると思いました。

免責事項:私は数年間GeoDatabaseチームでESRIに勤務し、GeoDatabaseコードのさまざまな部分(バージョニング、カーソル、EditSessions、履歴、関係クラスなど)の管理を担当していました。

ESRIコードのパフォーマンスの問題の最大の原因は、さまざまなオブジェクト、特にさまざまなGeoDatabase抽象化の「小さな」詳細を使用することの意味を理解していないことです。非常に頻繁に、会話がパフォーマンスの問題の原因として使用されている言語に切り替わります。場合によっては可能です。しかし、常にではありません。言語の議論から始めましょう。

1.-選択するプログラミング言語は、複雑なことをタイトなループで行う場合にのみ重要です。ほとんどの場合、これは事実ではありません。

部屋の大きな象は、すべてのESRIコードの中核にArcObjectsがあり、ArcObjectsはCOMを使用してC ++で記述されていることです。このコードとの通信にはコストがかかります。これは、C#、VB.NET、Python、または使用している他のすべてのものに当てはまります。

そのコードの初期化時に料金を支払います。一度だけ実行する場合、それは無視できるほどのコストになります。

その後、ArcObjectsとやり取りするたびに料金を支払います。

個人的には、C#でクライアント用のコードを書く傾向があります。それは、それが十分に簡単で高速だからです。ただし、データを移動したり、ジオプロセシングで既に実装されている大量のデータの処理を行うたびに、スクリプトサブシステムを初期化し、パラメーターを渡します。どうして?

  • すでに実装されています。では、なぜ車輪を再発明するのでしょうか?
  • 実際にはもっと速いかもしれません。「C#で書くよりも速い?」はい!たとえば、データのロードを手動で実装すると、.NETコンテキストの切り替えのコストをタイトループで支払うことになります。すべてのGetValue、Insert、ShapeCopyにはコストがかかります。GPで1つの呼び出しを行うと、そのデータロードプロセス全体がGPの実際の実装(COM環境内のC ++)で発生します。コンテキスト切り替えがないので、私はコンテキスト切り替えの代価を払いません-したがって、それはより高速です。

ええ、そうです。それでは、多くのジオプロセシング関数を使用する場合の解決策です。実際、注意する必要があります。

2. GPは、データを(不必要に)コピーするブラックボックスです

それは両刃の剣です。内部で何らかの魔法をかけ、結果を吐き出すブラックボックスですが、これらの結果は非常に頻繁に複製されます。9つの異なる関数を使用してデータを実行した後、100,000行をディスク上の1,000,000行に簡単に変換できます。GP関数のみを使用することは、線形GPモデルを作成するようなものです。

3.大規模なデータセットに対して多すぎるGP機能をチェーン化することは非常に非効率的です。GPモデルは(潜在的に)本当に本当に馬鹿げた方法でクエリを実行することと同等です

誤解しないでください。私はGPモデルが大好きです-それはいつもコードを書くことから私を救います。しかし、大規模なデータセットを処理する最も効率的な方法ではないことも認識しています。

クエリプランナーについて聞いたことはありますか?実行するSQLステートメントを調べ、GPモデルのように見える有向グラフの形式で実行計画を生成し、dbに格納されている統計を見て、最も多く選択することです。それらを実行する最適な順序。GPは、あなたが物事を置く順番でそれらを実行するだけです。なぜなら、それはもっと賢く何かをする統計がないからです- あなたはクエリプランナーです。そして何だと思う?実行する順序は、データセットに大きく依存します。あなたが物事を実行する順序は、日と秒の違いを生む可能性があり、それはあなた次第です。

「素晴らしい」とあなたは言います、私は自分で物事をスクリプト化せず、私がものを書く方法に注意します。しかし、GeoDatabaseの抽象化は理解していますか?

4. GeoDatabaseの抽象化を理解していないと簡単に噛み付く

問題を引き起こす可能性のあるすべてのことを指摘する代わりに、私がいつも目にするいくつかのよくある間違いといくつかの推奨事項を指摘させてください。

  • リサイクルカーソルのTrue / Falseの違いを理解する。この小さなフラグをtrueに設定すると、実行時の順序が大幅に速くなります。
  • データをロードするには、テーブルをLoadOnlyModeに設定します。挿入ごとにインデックスを更新する理由
  • IWorkspaceEdit :: StartEditingはすべてのワークスペースで同じように見えますが、それらはすべてのデータソースで非常に異なる獣であることを理解してください。エンタープライズGDBでは、トランザクションのバージョン管理またはサポートがあります。シェープファイルでは、非常に異なる方法で実装する必要があります。元に戻す/やり直しをどのように実装しますか?有効にする必要さえありますか(はい、メモリ使用量に違いが生じる可能性があります)。
  • バッチ操作または単一行操作の違い。ポイントのケースGETROWS対GetRowをは -これは、1行を取得するクエリを実行するか、複数の行をフェッチするために、1つのクエリを実行するとの間の差です。GetRowの呼び出しでのタイトループはひどいパフォーマンスを意味し、パフォーマンスの問題の原因#1です
  • UpdateSearchedRowsを使用する
  • CreateRowCreateRowBufferの違いを理解してください。挿入ランタイムの大きな違い。
  • IRow :: StoreおよびIFeature :: Storeが非常に重い多態性操作をトリガーすることを理解してくださいこれがおそらく、パフォーマンスが本当に遅い2番目の原因です。行を保存するだけでなく、これはジオメトリックネットワークに問題がないこと、ArcMapエディターに行が変更されたことを通知する方法、この行に関係するすべてのリレーションシップクラスを検証する方法ですカーディナリティが有効であることなどを確認してください。これで新しい行を挿入しないでください。InsertCursorを使用する必要があります
  • EditSessionでこれらの挿入を行いますか(必要です)?それは作る巨大なあなたが行うかどう違いを。一部の操作ではそれが必要です(そして処理が遅くなります)が、必要ない場合は、元に戻す/やり直し機能をスキップしてください。
  • カーソルは高価なリソースです。一度ハンドルを取得すると、一貫性と分離が保証され、コストがかかります。
  • データベース接続(ワークスペース参照を作成および破棄しない)およびテーブルハンドル(1つを開いたり閉じたりするたびに-いくつかのメタデータテーブルを読み取る必要がある)などのその他のリソースをキャッシュします。
  • FeatureClassをFeatureDatasetの内部または外部に配置すると、パフォーマンスに大きな違いが生じます。これは組織的な機能を意味するものではありません

5.そして最後に重要なこと...

I / Oバウンド操作とCPUバウンド操作の違いを理解する

正直に言って、これらのアイテムのすべてをさらに拡張し、おそらくそれらのトピックのすべてをカバーする一連のブログエントリを実行することを考えましたが、私のカレンダーのバックログリストは私に顔を平手打ちして怒鳴り始めました。

私の2セント。


5
ありがとう。私の代わりにこの記事を書いて(笑)の仕事をしてきたはずです
Ragi Yaser Burhum

3
+1ご意見をお寄せいただき、ありがとうございます。これは、私が受け取ることを目指していたタイプの応答です。二度投票できたら!! ArcGISScripting(python)ユーザーがこの回答から理解すべきことは、リンクはArcObjectsと.Netの概念を反映しているものの、基盤となるCOMオブジェクトは同じであるため、これらのオブジェクトを理解することで、あらゆる言語でコードを計画するのに役立ちます。ここにはたくさんの素晴らしい情報があります!!
OptimizePrime

1
@OptimizePrimeこれは素晴らしい要約です。そして、あなたは正しいです-あなたはESRI製品のうち、パフォーマンスを圧迫したい場合は、ArcObjectsのへの影響を無視することはできません
Ragi Yaser Burhum

1
おかげで、store()をカーソルの挿入で置き換え、アプリケーションの時間を大幅に節約しました!
superrache

5

一般に、パフォーマンスの計算のために、私はESRI関連のものの使用を避けようとします。あなたの例では、プロセスを段階的に行うことをお勧めします。最初のステップはデータを通常のpythonオブジェクトに読み込み、計算を行い、最後のステップは最終的なESRI空間形式に変換します。〜10,000のレコードの場合、おそらく処理のためにすべてをメモリに保存することで回避でき、これによりパフォーマンスが確実に向上します。


ご回答ありがとうございます。良い提案です。arcgisscriptingを使用する前に、必要な手順を実行するためにコードをリファクタリングし始めました。ArcInfoの時代からソフトウェアを使用した後、CPUのパフォーマンスとハードウェアの機能が向上し、ArcGIS Map / Info / Editor XXのパフォーマンスが停滞していることに不満を感じています。GPUの導入が物事を後押しするかもしれません。ESRIコードベースの適切なリファクタリングも役立ちますが、
OptimizePrime

1

使用しているハードウェアに応じて、ESRI Geocoderの例に表示されるオプションを検討することもできます。大規模なデータセットを分割し、Pythonの複数のインスタンスを実行して、ほぼマルチスレッドのアプローチを提供するフレームワークを提供します。ジオコーディングのパフォーマンスは、1台のPythonインスタンスでの1時間あたり180,000から、マシン上で8つの並列プロセスを起動したおかげで100万を超えるまでになりました。

できるだけ多くのデータを取得し、データをデータベースで機能させ、テーブルで機能的に機能させ、ESRIレルムで明示的なGISを使用するだけで、パフォーマンスが大幅に向上することがわかりました。


これらは素晴らしいアイデアです。このスクリプトでいくつかのプロセスをスレッド化する機会がありますが、ボトルネックがCOMライブラリとジオデータベースI / Oを初期化していることに気付きました。I / Oに関しては、単一の書き込みの必要性を減らしました。最適化にこれ以上時間を費やせば、上司にフィットするはずです。現在、1分間に60,000個のフィーチャを処理しています。
OptimizePrime

0

これらの他のフォーラムの投稿は、最適化のコンテキストにありますが、ラスターデータおよび全体的なものであるため、興味深いことがあります。

ArcGIS Geoprocessingツールを使用するPythonスクリプトをコンパイルしますか?

スタンドアロンPythonスクリプトでのArcGIS HydrologyツールボックスツールとArcCatalogを使用した処理時間

gp.scratchworkspace設定は、私が流域描写のために書いたいくつかのpythonコードで大きな違いをもたらしました。

元の質問に対するUPDATEの番号1と2を示すコード例を投稿できますか?その仕組みを見てみたいと思います(ただし、ここでのみフィーチャクラスデータを扱っていると仮定しています)

ありがとう、トム

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