Excluindo recursos da classe de recurso mais rapidamente usando o ArcPy?

8

Eu escrevi esse script que se repete em todas as classes de recursos em um determinado conjunto de conjuntos de dados de recursos e exclui todos os seus recursos. Parece fazer o trabalho, mas corre bem devagar. Existe algo que estou fazendo errado aqui ou existem maneiras óbvias de acelerar as coisas?

Estou usando DeleteFeatures_management para executar a ação. DeleteRows_management também parece funcionar.

import sys
import os
import arcpy
from arcpy import env
import datetime
import getpass

try:
    passwd = getpass.getpass("Enter the sde user password: ")

    sdeConnectionFileDir = os.environ.get("TEMP")
    databaseName = ""
    fileName = "temp.sde"

    # Delete any pre-existing SDE connection file.
    fullPath = sdeConnectionFileDir + '\\' + fileName
    if os.path.exists(fullPath):
        os.remove(fullPath)

    # Create temporary SDE connection file.
    arcpy.CreateArcSDEConnectionFile_management (
        sdeConnectionFileDir, fileName,
        "sdeserver", "5151", "",
        "DATABASE_AUTH", "my_sde_user", passwd,
        "SAVE_USERNAME", "SDE.DEFAULT", "SAVE_VERSION"
    )

    env.workspace = fullPath

    # ArcPy status codes.
    returnCodes = {'WARN' : 0, 'INFO' : 1, 'ERROR' : 2}

    featureDatasets = []
    featureDatasets.extend(arcpy.ListDatasets("dataset1*"))
    featureDatasets.extend(arcpy.ListDatasets("dataset2*"))
    featureDatasets.extend(arcpy.ListDatasets("dataset3*"))

    list = '[%s]' % ', '.join(map(str, featureDatasets))
    response = raw_input("\n***** WARNING!!! ***** \nAll data will be deleted from all feature classess in the following datasets: \n\n" + list + "\n\n |--> Type DELETE to begin removal: ")
    if response == "DELETE":
        print "\nStarted: " + str(datetime.datetime.now()) + "\n"
        for dataset in featureDatasets:
            print "Processing dataset: " + dataset
            for fc in arcpy.ListFeatureClasses("*", "ALL", dataset):
                rowCount = int(arcpy.GetCount_management(fc).getOutput(0))

                if rowCount > 0:
                    print "  -- Processing feature class: " + str(fc) + " (" + str(rowCount) + " rows)"
                    #arcpy.DeleteRows_management(fc)
                    arcpy.DeleteFeatures_management(fc)

        print "\nCompleted: " + str(datetime.datetime.now())

except Exception as e:
    if arcpy:
        arcpyErrors = arcpy.gp.getMessages(returnCodes['ERROR'])
        if arcpyErrors:
            sys.stderr.write(arcpyErrors + "\n")
    sys.stderr.write(str(e) + "\n")
    sys.exit(1)

EDIT -

Coloquei alguns temporizadores de desempenho no script e aqui estão os dados:

  • Hora de recuperar conjuntos de dados: 0: 00: 01.254000
  • Total de classes de recurso: 1682
  • Total de classes de recursos com dados: 124
  • Total de recursos processados: 190222
  • Tempo total de execução : 3 horas, 16 minutos

O colapso:

Conjunto de dados de recursos -> listar chamadas de classe de recursos:

* AVG   0:00:02
* MIN   0:00:01
* MAX   0:00:07
* COUNT 40
* TOTAL 0:01:08

Chamadas de contagem de recursos (na maioria das vezes):

* AVG   0:00:06
* MIN   0:00:01
* MAX   0:00:16
* COUNT 1682
* TOTAL 2:41:00

Chamadas de exclusão de recurso (reduzidas porque apenas as classes de recurso com linhas são processadas):

* AVG   0:00:17
* MIN   0:00:02
* MAX   0:03:22
* COUNT 124
* TOTAL 0:34:31
Andy Arismendi
fonte

Respostas:

14

Qual parte do script está ocupando a maior parte do tempo? Existem cerca de 5 outras etapas antes de você começar a excluir as coisas.

Convém dividir seu script em testes de tamanho reduzido. Por exemplo, em vez de criar um arquivo de conexão temporário, listando vários conjuntos de dados, listando seu conteúdo, contando seus registros e, finalmente, fazendo o que você deseja (excluindo recursos), basta passar em uma única classe de recurso com um pré-fabricado arquivo de conexão com DeleteFeatures e veja quanto tempo leva.

Se o desempenho for aceitável, crie outro teste para cronometrar o próximo ponto de problema em potencial: contagem de linhas. E outro para listar classes de recursos em um conjunto de dados de recursos e outro para listar conjuntos de dados de recursos em um geodatabase.

Se, por outro lado, DeleteFeatures não tiver um desempenho aceitável, pelo menos saberemos onde está o problema. Nesse caso, eu estaria mais inclinado a ver como o seu geodatabase é projetado:

  • Algum dos seus conjuntos de dados de recursos está com versão? Ao usar o controle de versão, existe um par adicional de tabelas A (adiciona) e D (exclui) para cada tabela com versão e, quando você exclui recursos, não está excluindo registros na tabela base, está adicionando registros à tabela D. Isso levará muito mais tempo do que se não tivesse versão.

  • Como todas as suas classes de recursos parecem estar em conjuntos de dados de recursos, elas participam do comportamento do banco de dados geográficos, como uma topologia ou rede geométrica? Quando você adiciona / remove / modifica recursos que participam do comportamento do banco de dados geográficos, há muito mais sobrecarga.

  • Observe também que, contrariamente à crença popular, os conjuntos de dados dos recursos não foram projetados para serem usados ​​como uma ferramenta organizacional:

    Existem conjuntos de dados de recursos no geodatabase para definir um escopo para uma referência espacial. Todas as classes de recursos que participam de relacionamentos topológicos entre si (por exemplo, uma rede geométrica) devem ter a mesma referência espacial. Os conjuntos de dados de recursos são uma maneira de agrupar classes de recursos com a mesma referência espacial, para que eles possam participar de relacionamentos topológicos entre si.

    Para a maioria dos usuários, os conjuntos de dados de recursos também têm uma qualidade organizacional natural, como uma pasta em um sistema de arquivos. Como para muitas aplicações GIS, a maioria dos dados tem a mesma referência espacial, a tentação de agrupar um grande número de classes de recursos em conjuntos de dados de recursos é irresistível.

    Os conjuntos de dados de recursos, no entanto, não são gratuitos. Quando você abre uma classe de recurso contida em um conjunto de dados de recurso para examinar suas propriedades ou desenhá-lo ou consultá-lo no ArcCatalog ™, ArcMap ™ ou em um aplicativo personalizado, todas as outras classes de recurso nesse conjunto de dados de recurso também são abertas. Isso é feito porque as atualizações de uma classe de recurso em um conjunto de dados de recursos podem potencialmente se espalhar para outras classes de recursos no conjunto de dados de recursos que participam de relacionamentos topológicos.

    De: Sistemas de informações geográficas multiusuário com ArcInfo 8 (abril de 2000)

    Portanto, isso pode ser outra fonte de sobrecarga, mesmo que eles não participem de uma topologia ou rede geométrica.

Além dos comandos deleteFeatures / DeleteRows do arcpy:

  • Se você tiver acesso ao comando de administração do SDE, poderá usar:

    sdetable -o truncate -t <tablename>

    Isso emite comandos de tabela truncada no seu DBMS, portanto deve ser muito mais rápido, mas observe que isso ignora o comportamento do banco de dados geográficos.

  • Usar o ArcSDESQLExecute para emitir TRUNCATE TABLEcomandos diretamente (novamente ignorando o comportamento do banco de dados geográficos ), mas isso é muito propenso a problemas, pois você precisaria emitir um para cada tabela que compõe uma classe de recurso (base, F, S, I, A, D, etc. .) Não fazer isso com cuidado e corretamente pode deixar seus dados em um estado inconsistente.

blah238
fonte
Isso é ótimo conselho. Vou colocar alguns timers para cada operação e postar os resultados. Pelo menos até o momento, parece que estou usando os métodos apropriados da API do ArcPy. Ainda estou aprendendo a API do ArcPy, por isso fiquei preocupado com a possibilidade de usar outro método.
Andy Arismendi
No que diz respeito ao arcpy, acho que DeleteRows e DeleteFeatures são os melhores que você pode fazer, mas adicionei algumas outras opções que podem valer a pena investigar, pelo menos, se isso for crítico em termos de tempo.
blah238
Adicionei algumas métricas de desempenho acima. Existem 1682 classes de recursos. Embora, em média, a contagem demorasse 1/3 do tempo de exclusão. As operações de exclusão concedidas processaram apenas classes de recursos com recursos. Vou tentar remover a contagem e passar todas as classes de recurso para DeleteRows_management e ver como isso ocorre. Também tentarei sdetable usando a opção truncar.
Andy Arismendi
2
Caramba, 1682 apresentam aulas ?! Definitivamente, eu procuraria um fluxo de trabalho alternativo para lidar com tantos dados. Quando você começa a falar sobre centenas de tabelas, realmente deve estar no back-end, trabalhando diretamente com o DBMS IMO. Tenha os seus DBAs cozinhar algo em PL / SQL ou algo :)
blah238
Apenas 124 classes de recursos tinham recursos, o restante estava vazio. BTW você acabou de me dar uma idéia! Talvez a criação do arquivo de conexão SDE usando uma conexão direta Oracle ajude a melhorar o desempenho. Vou tentar isso a seguir.
21812 Andy Arismendi
9

Se a atualização para o ArcGIS 10.1 (agora lançada) for uma opção, então eu a encontrei no PDF What's New in ArcGIS 10.1:

Nova ferramenta para excluir todas as linhas de uma tabela

A ferramenta de geoprocessamento TruncateTable no conjunto de ferramentas Tabelas pode ser usada para excluir todas as linhas de uma tabela ou classe de recurso. Você deve usar a ferramenta Truncar tabela em vez da ferramenta Excluir linhas quando desejar excluir todas as linhas de uma tabela ou classe de recurso.

Sua ajuda on-line pode ser encontrada aqui .

PolyGeo
fonte
1
Isto é muito mais rápido do que DeleteRows
nmpeterson
3
A única coisa é que ele não suporta tabelas com versões / classes de recursos.
Ruchira Welikala
5

Por que não excluir apenas os conjuntos de dados de recursos arcpy.DeleteFeatures_management(dataset)? Se você ainda precisa que o conjunto de dados do recurso exista, basta recriá-lo depois que ele for excluído.

nmpeterson
fonte
Eu preciso manter os conjuntos de dados do recurso e suas classes de recurso por perto, porque eles não são recriados rapidamente devido à combinação SDE / Oracle e existem muitas classes de recursos. Estou tentando excluir os recursos o mais rápido possível.
Andy Arismendi