您的位置:首页 > 博客中心 > 数据库 >

怎么提高ArcSDE 写入地理数据库的效率

时间:2022-03-14 16:27

link: http://blog.csdn.net/linghe301/article/details/20900615

2014-03-14 09:20?2686人阅读?

很多用户经常会有将数据写入ArcSDE地理数据库的操作,也时常会写入效率而烦恼,它们渴望不管多大多复杂的数据,尽可能的使用较少的时间写入到ArcSDE中,而往往用户写入ArcSDE也通过依赖于本身的业务需求,使用自定义的代码开发就非常常见了,那影响ArcSDE写入效率的因素就比较多了。

----------------------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

Blog: ? ? ? ? ? ? ? http://blog.csdn.net/linghe301

----------------------------------------------------------------------------------

代码因素

大多数用户可能还在使用ArcGIS Engine、空间SQL、ArcSDE API和WebAPI进行开发,针对后两者我不是很熟悉,也没有什么发言权,所以更多的以前面两种开发模式为例,看看在代码开发过程中是否有可以优化的余地。

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ArcGIS Engine ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

以下部分可以参考2011年Esri中国开发者大会《Geodatabase高效编程_李圣虎》,特此感谢!

该文档建议ArcGIS Engine的开发者仔细学习,里面介绍了很多提高效率的技巧和细节!

?

另外大家也可以参考:Geodatabase API best practices?

?

1:使用多线程

说实话,ArcGIS Engine是否支持多线程,大家的理解是不一样的。用资深人士解释就是ArcGIS Engine支持多线程,但是不支持多个线程之间的彼此调用。

下面就以更新多个要素类的字段来演示一下多线程的使用方法,以下都是伪代码。

编写一个更新要素类的函数,输入参数为要素类名称

  1. public?class?VersionEditing??
  2. ???{??
  3. ???????///?<summary>??
  4. ???????///?更新要素类指定字段值??
  5. ???????///?</summary>??
  6. ???????///?<param?name="parameter">要素类名称</param>??
  7. ???????public?void?UpdateFiledValue(object?parameter)??
  8. ???????{??
  9. ????........??
  10. ???????}??
  11. ?????}??

    编写多线程函数,调用这个更新要素类的函数

  12. private?void?MultiThreadEditing()??
  13. ????????{??
  14. ????????????VersionEditing?VersionEditing?=?new?GIS.VersionEditing();??
  15. ????????????//声明线程对象??
  16. ????????????Thread?thA?=?new?Thread(new?ParameterizedThreadStart(VersionEditing.UpdateFiledValue));??
  17. ????????????Thread?thB?=?new?Thread(new?ParameterizedThreadStart(VersionEditing.UpdateFiledValue));??
  18. ????????????//设置线程工作模型??
  19. ????????????thA.SetApartmentState(ApartmentState.STA);??
  20. ????????????thB.SetApartmentState(ApartmentState.STA);??
  21. ????????????//启动线程??
  22. ????????????thA.Start("featureclass1");??
  23. ????????????thA.Start("featureclass2");??
  24. ????????}??

    ?

    2:使用游标进行地理数据库编辑

    如果是批量进行数据编辑,不建议用户使用传统的Create Feature+Store的方法,而是使用insertCursor或者Update Cursor的方法。

  25. //建议的方法??
  26. public?static?void?InsertFeaturesUsingCursor(IFeatureClass?featureClass,?List?<??
  27. ????IGeometry?>?geometryList)??
  28. {??
  29. ????using(ComReleaser?comReleaser?=?new?ComReleaser())??
  30. ????{??
  31. ????????//?Create?a?feature?buffer.??
  32. ????????IFeatureBuffer?featureBuffer?=?featureClass.CreateFeatureBuffer();??
  33. ????????comReleaser.ManageLifetime(featureBuffer);??
  34. ?? ?
  35. ????????//?Create?an?insert?cursor.??
  36. ????????IFeatureCursor?insertCursor?=?featureClass.Insert(true);??
  37. ????????comReleaser.ManageLifetime(insertCursor);??
  38. ?? ?
  39. ????????//?All?of?the?features?to?be?created?are?classified?as?Primary?Highways.??
  40. ????????int?typeFieldIndex?=?featureClass.FindField("TYPE");??
  41. ????????featureBuffer.set_Value(typeFieldIndex,?"Primary?Highway");??
  42. ????????foreach?(IGeometry?geometry?in?geometryList)??
  43. ????????{??
  44. ????????????//?Set?the?feature?buffer‘s?shape?and?insert?it.??
  45. ????????????featureBuffer.Shape?=?geometry;??
  46. ????????????insertCursor.InsertFeature(featureBuffer);??
  47. ????????}??
  48. ?? ?
  49. ????????//?Flush?the?buffer?to?the?geodatabase.??
  50. ????????insertCursor.Flush();??
  51. ????}??
  52. }??

    ? ? ? 测试场景:从本地File Geodatabase中读取数据,向ArcSDE Geodatabase要素类中插入读取的数据;
    ? ? ? 数据情况:简单的线要素类,2721089条记录;
    ? ? ? 测试环境:硬件(T9600 CPU 4G内存)软件(Windows 7 64Bit Oracle 11g ArcGIS 10)
    ? ? ? 备注:测试结果中时间单位为秒
    技术分享

    ?

    3:游标

    游标分为类绑定游标: SearchCursor、UpdateCursor、InsertCursor和非类绑定游标:QueryDef Cursor。在使用游标使用过程中经常会遇到如下情况

  53. Public?Void?test()??
  54. {??????????????????
  55. ????????workspaceEdit.StartEditOperation();??
  56. ????????????????IQueryFilter?queryFilter?=?new?QueryFilter();??
  57. ????????????????queryFilter.WhereClause?=?clause;??
  58. ????????????????//是否重复绑定游标??
  59. ????????????????ICursor?updateCursor?=?table.Update(queryFilter,?true);??
  60. ????????????????comReleaser.ManageLifetime(updateCursor);??
  61. ????????????????int?fieldIndex?=?table.Fields.FindField("FWMC");??
  62. ????????????????IRow?temp?=?null;??
  63. ????????????????while?((temp?=?updateCursor.NextRow())?!=?null)??
  64. ????????????????{??
  65. ????????????????????temp.set_Value(fieldIndex,?"aaaa");??
  66. ????????????????????updateCursor.UpdateRow(temp);??
  67. ????????????????}??
  68. ????????????????workspaceEdit.StopEditOperation();??
  69. }??

    如果选择TRUE,说明使用资源回收游标,但是下一个游标还指向同一个内存地址,如果是FALSE,说明资源回收游标和内存地址,下一个游标还需要重新分配一个新的内存地址,这样无疑增加了服务器资源的开销,所以没有特殊需求,建议使用TRUE。

    ?

    关于游标的相关提示:

    查询游标(Search Cursor)

  • 在编辑会话中初始化SearchCursor可能导致缓存记录提交到数据库(触发DBMS写操作)
  • 通过SearchCursor获得的行支持Store和Delete操作

更新游标(Update Cursor)

  • 必须使用UpdateCursor提供的的UpdateRow和DeleteRow方法对通过UpdateCursor获得的行进行更新和删除操作
  • UpdateCursor提供的UpdateRow方法只能针对通过UpdateCursor获得的当前行进行操作
  • UpdateCursor不支持跨编辑操作使用,打开一个新的编辑操作时必须初始化一个新的更新游标
  • 使用UpdateCursor对复杂要类类进行更新时必须处于一个编辑会话中

插入游标(Insert Cursor)

  • 主要用于批量要素插入
  • 使用缓存,定时调用Flush将缓存写入数据库,调用InsertRow和Flush方法时要捕捉异常
  • 使用InsertCursor时关闭空间缓存

QueryDef 游标

  • 不能针对通过QueryDef Cursor获得的行进行Store和Delete操作
  • 在编辑会话中使用QueryDef Cursor会导致缓存提交到数据库

4:资源回收

尽可能使用Esri提供的MangeLifetime来管理ArcGIS Engine对象的生命周期,系统会自动进行维护,而不需要在使用类似以下方式进行释放资源了。(由于版本原因,可能有所不同)

?ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(o);

System.Runtime.InteropServices.Marshal.ReleaseComObject(o);

GC.Collect();

?

5:如果可能化,使用缓存来提高效率

  1. ///?<summary>??
  2. ????????///?执行空间缓存??
  3. ????????///?</summary>??
  4. ????????///?<param?name="pFWS">工作空间</param>??
  5. ????????///?<param?name="pEnv">缓存区域</param>??
  6. ????????private?void?SpatialCache(IFeatureWorkspace?pFWS,?IEnvelope?pEnv)??
  7. ????????{??
  8. ????????????if?(m_pWS?!=?null)??
  9. ????????????{??
  10. ????????????????ISpatialCacheManager3?pSCM?=?m_pWS?as?ISpatialCacheManager3;??
  11. ????????????????if?(!pSCM.CacheIsFull)??
  12. ????????????????{??
  13. ????????????????????pSCM.FillCache(pEnv);??
  14. ????????????????}??
  15. ?? ?
  16. ????????????????//执行空间操作代码??
  17. ?? ?
  18. ????????????????//清空缓存??
  19. ?? ?
  20. ????????????????pSCM.EmptyCache();??
  21. ???????????????? ?
  22. ????????????}??
  23. ????????}??

    ?

    更多了解:

    ?

    2:尽可能的使用存储过程

    如果可能的话,尽可能的使用存储过程来代替原始的单个SQL语句,这里面就不再解释存储过程的好处了。

    ?

    3:使用绑定变量而不是传入固定的值

    ?

    ?

    ----------------------------------------------------------------------------------

    版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

    Blog: ? ? ? ? ? ? ? http://blog.csdn.net/linghe301

    ----------------------------------------------------------------------------------

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 网络因素? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    网络的原因也是用户需要注意的,如果你的网络带宽、延迟都有问题,肯定会影响数据传输的效率的。这里我只是指出这是一个影响因素,因为不专业,所以不去更多的分析这个问题,但是用户需要留意该问题。

    ----------------------------------------------------------------------------------

    版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

    Blog: ? ? ? ? ? ? ? http://blog.csdn.net/linghe301

    ----------------------------------------------------------------------------------

    ?

    ? ? ? ? ? ? ? ? ? ArcSDE地理数据库因素(以Oracle为例) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??


    1:空间索引问题

    在ArcSDE地理数据库编辑过程中,系统会自动维护该编辑要素对象的空间索引,那么就会耗费一定的服务器资源,特别是在大数据量进行数据插入的过程中,无需进行空间索引的创建,可以等批量插入完成之后,统一创建空间索引,这样无疑就提高了操作效率。

    ArcGIS Desktop、ArcToolbox、ArcSDE命令行、Python都提供了管理空间索引的方法,当然ArcGIS Engine也提供了管理空间索引的接口

    ?

    IFeatureClassLoad.LoadOnlyMode

    ?

    2:如果进行更新操作,就需要留意索引

    用户进行更新,需要先查询出需要更新的要素对象,那么不管是通过属性索引或者空间索引进行查询,都需要这些索引对象有效。

    而且在编辑完毕之后,还需要对这些索引对象重新创建,保证新编辑对象的索引更新。

    ?

    3:数据库归档日志关闭

    如果是大数据量插入操作,如果没有特殊要求,可以将Oracle的归档日志进行关闭,因为归档日志主要记录数据的更高,特别是数据的修改和删除,对数据新增操作其实无需打开数据库归档,如果打开,系统会在批量新增数据的同时,写入大量的归档日志信息,也无疑也会降低编辑效率。

    ?

    4:禁用表空间日志

    虽然数据库的归档日志禁用之后,只是说数据库不再产生具体的归档日志文件,但是还需要进行非归档的循环日志写入,那么如果完全禁用日志的生成,需要禁用操作用户的表空间日志,这样在插入数据之后,系统就会记录比较少的日志信息。

    ?

    启用日志(Logging):用户进行表创建、索引创建、分区以及后续插入等操作产生REDO日志,作为数据恢复的依据。

    禁用日志(No Logging):以上相关操作不会产生REDO日志,进而也不能进行数据恢复,但是数据加载效率会大幅度提高。

    ?

    ?

    注意:这些操作是用户进行大数据量新增条件下,而且具有Oracle数据库知识的用户操作。

    ?

    操作示例:

    ?

    1:禁用归档日志

    sqlplus / as sysdba

    shutdown immediate;

    startup mount;

    alter database flashback off;

    alter database noarchivelog;

    alter database open;

    select flashback_on from v$database;

    archive log list;

    ?

    2:禁用表空间日志

    sqlplus /nolog

    connect / as sysdba;

    select ‘ALTER TABLESPACE ‘ || CHR(34) || NAME || CHR(34) || ‘NOLOGGING;‘

    FROM V$TABLESPACE

    WHERE NAME NOT IN (‘SYSTEM‘,‘SYSAUX‘,‘USERS‘,‘TEMP‘,‘UNDOTBS1‘)ORDER BY NAME;

    ? ?

    ALTER TABLESPACE "PM_BDATA" NOLOGGING;

    ALTER TABLESPACE "PM_BINDEX" NOLOGGING;

    ALTER TABLESPACE "PM_BDATA_TOPO" NOLOGGING;

    ?

    3:当用户只需完毕之后,在进行表空间日志启用和归档日志的启用即可。

    ?

    4:启用表空间日志

    sqlplus /nolog

    connect / as sysdba;

    select ‘ALTER TABLESPACE ‘ || CHR(34) || NAME || CHR(34) || ‘LOGGING;‘

    FROM V$TABLESPACE

    WHERE NAME NOT IN (‘SYSTEM‘,‘SYSAUX‘,‘USERS‘,‘TEMP‘,‘UNDOTBS1‘)ORDER BY NAME;

    ALTER TABLESPACE "PM_BDATA" LOGGING;

    ALTER TABLESPACE "PM_BINDEX" LOGGING;

    ALTER TABLESPACE "PM_BDATA_TOPO" LOGGING;

    ?

    5:启用归档日志

    sqlplus / as sysdba

    alter system set db_recovery_file_dest_size=10G scope=spfile;

    alter system setdb_recovery_file_dest=‘C:\oradata\flash_recovery_area‘ scope=spfile;

    alter system setlog_archive_dest_1=‘LOCATION=USE_DB_RECOVERY_FILE_DEST‘ scope=spfile;

    shutdown immediate;

    startup mount;

    alter database archivelog;

    alter database flashback on;

    alter database open;

    select flashback_on from v$database;

    archive log list;

    ?

    5:版本编辑的状态压缩

    这个问题我就不再赘述了,该博客无数次提及这个问题,感兴趣的用户可以在本博客搜索"版本压缩"或者"Compress"。

    ?

    6:Oracle参数

    比如足够大的SGA和PGA,典型Oracle参数的设置如Open_Cusors、db_writer_processes等

    ?

    7:其他因素

    当然,如果用户的硬件环境足够好,比如数据与索引分开存储、分区表、RAC架构等也会为批量写入数据提高效率。

    注意;严格禁止用户在OLTP环境下使用Oracle的并行计算,因为这样会严重造成资源占用问题。

    ?

    ?

    ----------------------------------------------------------------------------------

    版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

    Blog: ? ? ? ? ? ? ? http://blog.csdn.net/linghe301

    ----------------------------------------------------------------------------------

热门排行

今日推荐

热门手游