ArcGISScripting和大型空间数据集的性能


38

我目前正在使用arcgisscripting模块编写python脚本,以处理少量表(总数为8)标准化的相当大的数据集(总计10,000条记录)。该过程包括基于坐标元组(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作为表。

这三件事使用了一个脚本,该脚本将100,000+个要素从30分钟转换为30-40秒,这其中包括关系类。不能轻易使用它们,上面的大多数方法都占用大量内存,如果不注意,可能会导致问题。


1
您是否尝试过使用其他存储格式?文件地理数据库如何执行?
Derek Swingley 2011年

文件地理数据库的性能比个人地理数据库的性能稍差。我昨天花费了很多时间来设置和调整ArcSDE实例,以测试企业格式的性能。我会告诉你我的发现
OptimizePrime

2
现在这对您无济于事,但是在新版本的数据访问模块中,Python 10.1中的游标性能得到了很大的提高(平均情况下,幅度范围处于某种数量级)。
詹森·谢勒

In_memory使用了该InMemoryWorkspace edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriDataSourcesGDB/...其中,行任意数量的,之后一切转储到ScratchWorkspaceFactory(即FileGDB),并依赖于FileGDB做所有的工作
鸭脚稗亚瑟Burhum 2011年

Answers:


56

尽管已经回答了这个问题,但我认为我可以给我2美分。

免责声明:我在GeoDatabase团队的ESRI工作了几年,负责维护GeoDatabase代码的各个部分(版本,游标,EditSession,历史记录,关系类等)。

我认为ESRI代码的性能问题的最大根源不是不了解使用不同对象的含义,尤其是各种GeoDatabase抽象的“小”细节!因此,通常情况下,对话会切换为导致性能问题的原因的语言。在某些情况下可以。但并非一直如此。让我们从语言讨论开始,然后再往回走。

1.-您选择的编程语言仅在执行复杂且紧密循环的事情时才有意义。在大多数情况下,情况并非如此。

房间里最大的麻烦是,在所有ESRI代码的核心处,都有ArcObjects-并且ArcObjects是使用COM用C ++编写的。与该代码进行通信需要一定的费用。对于C#,VB.NET,python或您正在使用的其他任何工具都是如此。

您需要在初始化该代码时付出代价。如果只进行一次,则成本可以忽略不计。

然后,您需要为以后每次与ArcObjects进行交互付出的代价。

就个人而言,我倾向于使用C#为客户编写代码,因为它既简单又快速。但是,每次我要移动数据或对地理处理中已经实现的大量数据进行一些处理时,我都只是初始化脚本子系统并传递参数。为什么?

  • 它已经实现。那么,为什么要重新发明轮子呢?
  • 实际上可能更快。“比用C#编写还快?” 是! 例如,如果我手动实现数据加载,则意味着我要付出紧密循环中的.NET上下文切换的代价。每个GetValue,Insert,ShapeCopy都有成本。如果我在GP中进行一次调用,则整个数据加载过程将在GP的实际实现中进行-在COM环境中以C ++进行。我不为上下文切换付出任何代价,因为它不存在-因此速度更快。

嗯,是的,因此解决方案是否要使用很多地理处理功能。实际上,您必须要小心。

2. GP是一个黑匣子,可在周围复制数据(可能不必要)

这是一把双刃剑。这是一个黑匣子,内部会做一些魔术,并吐出结果-但是这些结果通常是重复的。通过9种不同的功能运行数据后,可以轻松地将100,000行转换为磁盘上的1,000,000行。仅使用GP函数就像创建线性GP模型一样,而且...

3.对于大型数据集,链接太多的GP函数效率很低。GP模型(潜在地)等效于以一种非常愚蠢的方式执行查询

现在不要误会我的意思。我喜欢GP模型-它使我免于一直编写代码。但我也知道,这不是处理大型数据集的最有效方法。

大家都听说过查询计划器吗?工作是查看要执行的SQL语句,以有向图的形式生成执行计划,该执行图看起来很像GP模型,查看存储在数据库中的统计信息,然后选择最执行它们的最佳顺序。GP只是按照您放东西的顺序执行它们,因为它没有统计信息可以更智能地执行任何操作- 您是查询计划者。你猜怎么着?执行事情的顺序非常取决于数据集。您执行事情的顺序可以使天和秒有所不同,这取决于您自己决定。

你说“好”,我不会自己编写脚本,并且要小心写东西。但是您了解GeoDatabase抽象吗?

4,不了解GeoDatabase抽象会轻易咬你

我没有指出可能会给您带来问题的每件事,而是让我指出了我经常看到的一些常见错误和一些建议。

  • 了解回收游标的True与False之间的区别。将此小标志设置为true可以使运行时快几个数量级。
  • 将表置于LoadOnlyMode进行数据加载。为什么要在每次插入时更新索引?
  • 可以理解,即使IWorkspaceEdit :: StartEditing在所有工作空间中看起来都一样,但它们在每个数据源上都是非常不同的野兽。在企业GDB上,您可能具有版本控制或事务支持。在shapefile上,必须以非常不同的方式来实现它。您将如何实施撤消/重做?您甚至需要启用它吗(是的,它可以在内存使用方面有所作为)。
  • 批处理操作或单行操作之间的区别。以GetRow与GetRows为例 -这是执行查询以获取一行或执行查询以获取多行之间的区别。调用GetRow的紧密循环意味着糟糕的性能,这是性能问题的元凶#1
  • 使用UpdateSearchedRows
  • 了解CreateRowCreateRowBuffer之间的区别。插入运行时的巨大差异。
  • 了解IRow :: Store和IFeature :: Store会触发超重的多态操作。这可能是导致性能真正下降的第二个原因。它不只是保存行,这是确保几何网络正常的方法,可确保ArcMap编辑器收到行已更改的通知,并通知与该行有任何关系的所有关系类进行验证确保基数有效,等等。您不应以此插入新行,而应使用InsertCursor
  • 您是否要(需要)在EditSession中进行这些插入?不管您是否这样做,都会产生巨大的变化。某些操作需要它(并使其变慢),但是当您不需要它时,请跳过撤消/重做功能。
  • 游标是昂贵的资源。一旦处理了一个问题,就可以确保自己具有一致性和隔离性并且要付出代价
  • 缓存其他资源,例如数据库连接(不要创建和销毁Workspace引用)和表句柄(每次打开或关闭一个资源-都需要读取几个元数据表)。
  • 将FeatureClass类放在FeatureDataset的内部或外部会对性能产生巨大的影响。这并不是组织功能!

5,最后同样重要的是...

了解I / O绑定和CPU绑定操作之间的区别

老实说,我想在这些项目的每一个上进行更多的扩展,或者做一系列涵盖每个主题的博客条目,但是我日历的待办事项列表只是打了我一脸,就开始对我大吼大叫。

我的两分钱。


5
谢谢。我应该一直在做工作,而不是写这篇文章哈哈
Ragi Yaser Burhum 2011年

3
+1非常感谢您的宝贵意见Burhum先生。这是我希望收到的回应类型。如果我可以投票两次,我可以!尽管这些链接反映了ArcObjects和.Net概念,但ArcGISScripting(python)用户应该从中得到的好处是,底层的COM对象是相同的,了解这些对象将有助于您更好地计划任何语言的代码。这里有很多很棒的信息!
OptimizePrime

1
@OptimizePrime这是一个很棒的总结。而且您是对的-如果您想从ESRI产品中挤出性能,就不能忽略ArcObjects的含义
Ragi Yaser Burhum 2011年

1
谢谢,我通过插入游标替换了store()并在我的应用程序中节省了很多时间!
superrache

5

通常,对于性能计算,我会尽量避免使用任何与ESRI相关的东西。对于您的示例,我建议分步进行此过程,第一步是将数据读取到普通的python对象中,然后进行计算,最后一步是转换为最终的ESRI空间格式。对于约1万条记录,您可能会避免将所有内容存储在内存中进行处理,这将带来明显的性能提升。


感谢您的答复。这是一个很好的建议。在使用arcgisscripting之前,我已经开始重构代码以执行所需的过程。自从ArcInfo时代开始使用该软件后,我发现CPU性能和硬件功能的提高令人沮丧,ArcGIS Map / Info / Editor XX的性能却停滞不前。也许GPU的引入可能会推动事情发展。尽管对ESRI代码库的良好重构也可能会有所帮助
OptimizePrime

1

根据您拥有的硬件,您可能还考虑了ESRI Geocoder示例中显示的选项。它为您提供了一个分解大型数据集并运行多个python实例的框架,从而为您提供了几乎多线程的方法。我看到地理编码的性能从单个Python实例的每小时18万个提高到超过一百万个,这要归功于我的机器上分解了8个并行进程。

我已经看到,尽我所能,将数据工作保存在数据库中,将功能工作保存在表中,仅在ESRI领域中使用显式GIS可以大大提高性能。


这些都是很棒的主意。我有机会在此脚本中线程一些进程,但是我发现瓶颈正在初始化COM库和Geodatabase I / O。关于I / O,我减少了一次写入的需要。如果我花更多的时间进行优化,那么我的老板会很合适;)因此,如果他要求更多的性能,那么我将线程作为最后的性能压力。目前,我每分钟要处理60,000个功能。
OptimizePrime

0

您可能会发现这些其他论坛帖子很有趣,因为它们在优化上下文中,但是对于栅格数据和总体而言:

编译使用ArcGIS地理处理工具的Python脚本?

在独立的Python脚本和ArcCatalog中使用ArcGIS Hydrology工具箱工具处理时间?

gp.scratchworkspace设置在我为进行分水岭划界而编写的某些python代码中对我产生了很大的影响。

您能否在原始问题中张贴一些代码示例,以在UPDATE中演示数字1和2?我很想了解其机制(尽管我假设您仅在此处处理要素类数据)

谢谢汤姆

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.