ArcView 3.x Avenue Bitmaps (Registerkarten?) Im Vergleich zu ArcView 10 Python Cursors


9

Hinweis: Obwohl diese Frage eine Antwort enthält, sind weitere Tipps zur Optimierung eines Cursorprozesses sehr willkommen. Ich werde nach Updates suchen.

Derzeit versuchen mein Chef (der in Avenue arbeitet) und ich (der in Python arbeitet) beide, dasselbe Problem zu lösen. Vielmehr haben wir beide es gelöst, aber die Geschwindigkeit, mit der unsere Lösungen arbeiten, ist ... gelinde gesagt unzusammenhängend. Was sein Skript in 2 Stunden verarbeitet, kann bis zu 6 Stunden dauern. Der einzige wirkliche Unterschied in der Syntax und Implementierung in der Logik besteht in den Bitmaps von 3.x und den Cursors von 10.x. Wir beide:

1) Speichern Sie die Werte aus Tabelle 1.
2) Verwenden Sie diese Werte, um eine Zeile in Tabelle 2 abzufragen.
3) Speichern Sie die Werte aus Tabelle 2 zum Einfügen in Tabelle 3 als neue Zeile.

In beiden Skripten werden diese Prozesse in zwei verschachtelten Schleifen abgeschlossen. Ist dies ein zu erwartendes Ereignis, bevor ich mich mit der wunderbaren Welt der Codeoptimierung befasse, wenn ich die Leistung von Avenue-Skripten mit Python vergleiche? Dies ist nicht das erste Mal, dass seine Skripte meine in Bezug auf die Betriebszeit deutlich übertroffen haben. Daher würde ich gerne wissen, ob ich etwas beachten sollte, bevor ich mich für schreckliche Skripte kreuzige.

Hier ist mein Skript ohne überflüssige Teile:

import arcpy
import time
import sys
import os

def recordfindcopy(inFile,query,outFile):
    findRecord = arcpy.SearchCursor(inFile,query)
    for record in findRecord:
        copyRecord = arcpy.InsertCursor(outData) # <--- D'oh! (See answer)
        field = record.FIELD
        copy = copyRecord.newRow()
        copy.FIELD = field
        copyRecord.insertRow(copy)

StreetsFileList = [r"Path", 
                r"Path"]

for sfile in StreetsFileList:
    inStreets = sfile
    inTable = r"Path"
    outData = r"Path"
    fsaEntry = arcpy.SearchCursor(inTable)
    for row in fsaEntry:
        id = row.ID
        sQuery = "ID = %s " % (str(id))
        recordfindcopy(inStreets,sQuery,outData)

EDIT : Angesichts einiger der bisherigen Kommentare frage ich mich, ob es einen besseren Weg gibt, dies über Joins zu tun, obwohl ich angesichts der brobdingnagischen Größe (Wort des Tages!) Der Tabellen zweifelhaft bin. Das Herzstück der Verarbeitung besteht darin, Informationen aus einer Tabelle an übereinstimmende Datensätze in einer zweiten Tabelle anzuhängen und eine dritte Tabelle zu erstellen, die nur die wichtigen Felder enthält. Ich wollte dies mit SDE versuchen, aber das scheint keine verfügbare Option zu sein. Gedanken? Ich entschuldige mich, wenn meine Fragen immer so involviert sind , aber ich versuche, einem langjährigen Ärger auf den Grund zu gehen.

Beantwortet : Jakubs einfacher Vorschlag allein reduzierte die Verarbeitungszeit von 30 Sekunden pro 500 Datensätze auf 3 Sekunden pro 500 Datensätze. Das erneute Starten des Einfügecursors bei jeder Einfügung verlangsamte die Dinge erheblich (offensichtlich). Dies ist möglicherweise nicht die beste Optimierung, die man für diesen Prozess durchführen kann, wenn man die Geschwindigkeit von ArcView 3.x berücksichtigt. Für meine Zwecke reicht dies derzeit jedoch aus. Weitere Vorschläge sind herzlich willkommen!


1
Möchten Sie Ihr Skript veröffentlichen? Ich kenne keine Allee / Python mit GP-Benchmarks.
Derek Swingley

Tabellenverknüpfungen und Abfragen sind in alten ArcView 3.2 (avenue) viel schneller als in ArcGIS 8.x bis 10. * arcpy / python. Grundsätzlich aufgrund der Menge (viel mehr) an Code in ArcGIS-Produkten.
Mapperz

2
@ Mapperz Du hast ganz recht. Die zeilenweise Verarbeitung in ArcView 3.x ist jedoch aufgrund des 10.000-fachen Interpretationsaufwands für jede Anforderung äußerst langsam (ich habe dies verglichen). Wenn man Schleifen vermeiden kann - indem Sie "High Level" -Anfragen wie Verknüpfungen und Abfragen verwenden, wie Sie vorschlagen -, schlägt ArcView 3.x ArcGIS die Nase vorn, aber es ist plausibel, dass in einem Kopf-an-Kopf-Test explizite Schleifen über Datensätze durchgeführt werden , könnte man mit relativ geringem Vorsprung gewinnen.
whuber

@Whuber @Derek Thar es sein.
Nathanus

Antworten:


2

Ich bin nicht neu in der Programmierung, aber sehr neu in Python, also nimm das mit einem Körnchen Salz ...

copyRecord = arcpy.InsertCursor(outData)

Sollte der Einfügecursor nicht vor der For Next-Schleife gesetzt werden? Mir scheint, wenn der Pfad zu den "out" -Daten in der Variablen "outData" gespeichert ist, muss er nicht jedes Mal zurückgesetzt werden, wenn Sie iterieren. Ich würde denken, dass dies die Dinge erheblich beschleunigen sollte.


Guter Fang. Ich werde es versuchen, wenn ich nächste Woche wieder im Büro bin.
Nathanus

5

Ich gehe davon aus, dass Sie ArcPy oder Arcgisscripting um 9.3 verwenden. In jedem Fall beschleunigen die Techniken hier Ihre Verarbeitung ... vielleicht besser als Ihre Chefs.

Das erste, was Sie tun müssen, ist das Nachschlagen und Einfügen mit einem anderen Medium als dem Speicher wird Ihre Prozesse verlangsamen. Avenue ist für eine schnelle Arbeit optimiert und verwendet eine C \ C ++ - Codebasis (korrigieren Sie mich, wenn ich mich irre), die bei E / A von Natur aus schneller ist als die meisten anderen Sprachen. Python ist auch schnell (genauso schnell), es sei denn, das Einbinden in c-Bibliotheken zur Ausführung von Vorgängen wie ArcPy oder Arcgisscripting ist mit einem Mehraufwand verbunden.

Versuchen Sie dies zuerst:
1. Kopieren Sie die Tabellen, die Sie verwenden müssen, mit den folgenden Methoden in den Speicher.

  • gp.CopyFeatures ("Pfad zur Feature-Class \ Feature-Class-Name", "'in_memory' \ Feature-Class-Name") - für Feature-Classes und;
  • gp.CopyRow ("Pfad zur Feature-Class \ FeatureTableName", "'in_memory' \ FeatureTableName") - für Tabellen in einer 'in_memory'-Feature-Class oder -Tabelle.

    Auf diese Weise können Sie Speicher wie RAM-Disk verwenden und viel Disk-Thrashing sparen. Sie können auch eine Feature-Class oder Tabelle im Speicher erstellen, indem Sie den Parameter FeatureDataset durch 'in_memory' ersetzen.

Verwenden Sie so oft wie möglich Python-Container. Dies erhöht auch die Geschwindigkeit.

Schließlich ist die Reihenfolge für Effizienz beim Lesen und Schreiben von Informationen für ESRI-Formate

  1. Shapefile (traurig aber wahr)
  2. Persönliche Geodatabase
  3. Datei Geodatabase
  4. ArcSDE (auch bei direkter Verbindung ist es langsamer)

Probieren Sie diese Vorschläge aus, da ich versuche, eine Liste der Dinge zusammenzustellen, die hier auf gis.stackexchange.com funktionieren. Siehe hier


Die Speicheroption scheint nützlich zu sein, aber die kombinierte Macht der Tabelle, die ich gegen Uhren abfrage, liegt bei fast 1 GB. Ich glaube, ich habe genug RAM, um dies zu ermöglichen, aber riskiert die schiere Größe des Tisches einen gewaltsamen Absturz? Was ist ein Python-Container?
Nathanus

Ich bin überrascht, dass Sie persönliche GDB so schnell platzieren wie Datei-GDB, da dies meiner Erfahrung nach direkt umgekehrt ist. Es wäre interessant, das irgendwo / zu einer bestimmten Zeit zu erkunden.
Matt Wilkie

Es mag der Prozess sein, mit dem ich gerade arbeite, aber ich habe festgestellt, dass eine Datei-GDB langsamer ist, aber nur gerade. Ich würde sagen, dass sie gleichwertig sind, und ich würde eine Datei-GDB nur aufgrund von Dateibeschränkungen einer persönlichen GDB vorziehen. Ich bin sehr daran interessiert, einen Benchmark dafür zu entwickeln. Möchten Sie mir helfen, einige Tests zu definieren?
OptimizePrime

Ich habe versucht, das Shapefile zu speichern, und das schien wenig zu helfen ... tatsächlich hat das Skript kurz danach die Verarbeitung eingestellt.
Nathanus

3

Ich wette, es ist nicht so, dass Avenue schneller als Python ist, sondern dass ArcView3 schneller als ArcGIS ist (bei dem, was Sie versuchen zu tun).

Da dies vom Klang her im Wesentlichen eine nicht räumliche Übung ist, möchten Sie möglicherweise mit dem direkten Zugriff auf die Datenbanktabellen experimentieren (z. B. nicht arcpy verwenden), und zwar mit etwas wie dbfpy oder odbc (ich habe keines von beiden selbst ausprobiert). Persönlich habe ich festgestellt, dass die Befehlszeile ogr2ogr der gdal / ogr- Suite um Größenordnungen schneller ist als gleichwertige Transaktionen in arcgis. Ich habe mich jedoch nur leicht mit den OGR-Abfragefähigkeiten befasst und nichts mit nur den Python-Bindungen erstellt, sodass ich nicht weiß, ob sich diese Geschwindigkeit überträgt.


Das einzige Problem dabei ist, dass ich nicht-räumliche Daten an räumliche Daten anhänge. IE Ich nehme das ShapeFeld zusammen mit einigen anderen und erstelle einen neuen Datensatz, der die Geometrie und die zusätzlichen nicht räumlichen Daten enthält. Werden dpfpy und odbc bewegte ShapesFelder (und ihre Geometrie) berücksichtigen ?
Nathanus

Es würde nicht mit Shapefiles funktionieren, da Shapees nicht in der .dbf gespeichert ist. Theoretisch könnte es mit einer persönlichen Geodatabase (.mdb) funktionieren, die odbc verwendet, aber ich bin misstrauisch gegenüber diesem Ansatz, zumal es mit OGR bereits eine bewährte Route gibt, die sowohl Shapefile als auch Personal GDB bereits kennt.
Matt Wilkie

1

Dies ist im Moment keine besonders hilfreiche Antwort, aber warten Sie auf ArcGIS 10.1. Auf dem diesjährigen Esri Dev-Gipfel wurde uns mitgeteilt, dass die Unterstützung für arcpy 10.1-Cursor vollständig neu geschrieben wurde und erheblich schneller ist. Während des Plenums gab es einen Anspruch auf Geschwindigkeitsverbesserungen von etwa 8x.


Danke für die Auskunft. Etwas, auf das man sich freuen kann, wenn nichts anderes.
Nathanus
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.