为了提高空间查询的性能,ArcSDE采用空间索引的机制。是一个覆盖整个要素类的两维索引,类似于一般的道路图上的索引网格。ArcSDE可以赋予三层空间索引网格,每个网格层都具有自己的格网大小。第一层网格为必需,它的格网尺寸最小;而第二和第三层可选,它们的网格可以通过设置为0使之无效。如果有效,第二层网格大小必须至少比第一层网格大三倍,而第三层网格大小也必须至少比第二层网格大三倍。
建立空间索引
每次向business表添加要素类时,会为它自动创建一个的空间索引。ArcSDE服务器在整个要素类的生命周期内都管理它的空间索引。当插入、更新或者删除要素时,空间索引会被自动更新。load-only模式会禁止空间索引的管理,直到载入数据结束。这种做法充分地提高了载入的性能,并且在大批量载入数据时必不可少。Load-only模式不允许SQL之外的查询操作。
数据载入结束后,返回normal模式,空间索引就可用了。从normal I/O模式到load-only I/O模式的转换会重建空间索引。在normal I/O模式下,插入、更新或者删除要素会更新空间索引。
ArcSDE首先将每个要素的范围覆盖到最低层的网格,获得网格数量。如果要素超过四个格网,ArcSDE将该要素提升到更高层次的网格(如果定义了更高层次的网格)。ArcSDE会一直提升要素到更高层次网格,直到该要素位于四个格网之内或者已到达最高层次的网格水平。在最高一层网格,图形可以被超过四个的格网索引。
ArcSDE将要素的格网和相应的shape ID、和要素范围一起添加到空间索引表中。网格层次和每个格网都进行编码,如下例:该要素类有两个网格层次。面状图形101位于第1层的第4号格网,那么空间索引表中就添加了一条记录,因为该要素在四个格网之内(事实上是一个格网)。面状要素102的范围位于第一层网格的格网1到8中。因为该要素的范围超出了四个格网,所以该要素被提升到第二层,在第二层中它位于两个格网之内。因此,要素102被第二层网格索引,并在空间索引表中添加了2条记录。
空间查询和空间索引
空间查询,比如查找某个州边界内的所有湖泊,就会使用空间索引。空间索引会被使用,除非SE_stream_set_spatial_constraints函数中的查找顺序设置为SE_ATTRIBUTE_FIRST。当查找顺序设为SE_ATTRIBUTE_FIRST时,ArcSDE忽略空间索引,而采用属性条件作为where子句查找满足条件的要素类中的记录。当使用空间索引时,ArcSDE通常按照下面的过程执行查询:
定义范围。范围可以之间由应用程序定义,比如ArcMap的zoom in工具定义的范围。此外,范围也可以由其他的要素范围来确定。
连接(Join)空间索引表和要素表,返回与该范围相交的格网。
连接(Join)要素表和business表,应用属性条件中的where子句进行更进一步的查询。
调整空间索引
格网的大小影响空间索引表的大小。设置空间索引在于寻找格网大小的平衡点—较小的格网会使每个要素对应较多的格网,也就需要空间索引表中的更多记录。由于客户端应用程序和空间数据的特征在各个系统之间差异很大,所以没有单一的适合所有情形的空间索引,有时需要尝试不同的格网大小和网格层次的配置。
sdelayer命令有几个操作选项可以通过改变格网大小和添加新的网格层次优化空间索引(’alter’操作选项)。‘stats’和‘si_stats’操作显示当前空间数据特征和空间索引信息。
如下为一些提高空间查询性能的方法:
考虑需要多少个网格层次,而且记住ArcSDE服务器为每个网格层次扫描一次空间索引表。经常一个网格层次对一个要素类而言就是最好的解决方法,即使认为将几何图形分布在多个不同的网格层次可以减少空间索引表的入口。
对于纯点状类型的要素类,使用一个网格层次,而且考虑增大格网大小。空间查询一般处理点状图形要比其他类型快。
监视空间索引。如果数据经常发生变化,调整空间索引会很困难。调整措施取决于空间数据的结构。当空间数据变化时,定期访问空间索引。
根据具体应用建立空间索引。将应用程序窗口大小和空间索引网格大小相匹配。
对于未知的或者变化的应用程序窗口,开始定义一个网格层次,格网大小为要素平均范围大小的3倍。可以利用如下的查询获得要素的平均大小:
select (avg(emaxx -eminx) + avg(emaxy - eminy)) / 2 from f
(where is the layernumber of the feature class)
根据数据种类设计要素类,比如类型、几何大小、和分布情况。有时精心设计的要素类会更加充分地提高空间查询的性能。
查看空间索引统计值
sdelayer命令的空间索引统计操作‘si_stats’,能够有助于确定优化的空间索引网格大小。优化网格大小取决于所有要素几何图形的空间范围、要素几何空间范围的差异、和要对该要素类进行的查询类型。以下是一个si_stats输出的例子:
$ sdelayer -osi_stats -l victoria,parcels -u av -p mo -i sde81
输出结果显示每个网格层次的统计值:
网格层次和格网大小
当前网格层次总的空间索引记录数
当前网格层次种存储的图形总数
每个图形的空间索引比率
分组的图形数量和百分比。表明图形空间索引在该网格层次如何分组。
每个网格的图形平均数
每个网格的最大数量
完全在一个网格中的图形的百分比
ArcSDE是基于不同类型的DBMS采用的不同空间索引建构方式,我们知道,在数据库中建立索引后,查询速度可以得到有效的提高。一般情况下,我们遇到的ArcSDE的索引都是多层次Index Grid的方法。即对一个要素类建立三级的Grid Index记录,请注意看我们要素一个要素类时Geometry中的属性,会有Grid 1、Grid 2和Grid 3三个参数,其中一般只建立了一个Grid。所谓Grid Index是人为将整个范围的要素类根据Grid的参数划分为N个网格,然后在Schema表(S表)中记录处于这个网格内的要素,如下图:
上图中是ARCSDE针对不同数据库采用的索引类型.
截至到ArcGIS桌面10 SP1发布之前
1:在ArcGIS9的桌面,在Geodatabase里面(PGDB、FGDB、ArcSDE GDB)创建一个表(Table),如果表的名称以gdb开头的(gdb、gdb1、gdbsdf、gdb_3d等)创建之后都看不到这个表,其实是存在该表的,如果你再创建一个同名的表会提示该表以存在,可以使用PGDB打开Access查看,创建要素类没有问题。ArcGIS10当中是没有这个问题的。
问题分析:目前只是猜测,因为ArcGIS9的GDB Schema都是以GDB_开头的表,用户在ArcCatalog里面是看不到这些Schema的,猜测有可能是以GDB开头的表给屏蔽掉了,不显示,但是ArcGIS10当中虽然说精简了GDB的Schema,但是还是有四个以GDB开头的表,ArcGIS10创建表是可以看到的,有点诧异,可能ArcGIS10把这四个表的表名称直接写死到程序里面了。
2:在使用ArcGIS桌面导入导出数据时,因为默认使用ArcGIS创建的要素类等其他对象系统都会创建一个ObjectID字段,是一个唯一标识,有些用户会使用这个ObjectID,可能会记录相应的ObjectID来对应指定的要素,但是在数据导入导出的过程中,尤其是导入,用户会很郁闷这些ObjectID重排,那么用户这边就无法来使用这个ObjectID,该怎么办呢?
问题分析:用户使用导入导出应该都是使用的Import/Export工具,该工具是重排ObjectID,建议用户使用直接对数据集或者要素类对象Copy/Paste,使用这种方式就不会对ObjectID重排,原来是什么就是什么,大家不妨可以试试。
3:在使用ArcGIS桌面导入数据过程中以Import为例,在导入框中的“Output Location”提示一个小红叉,该路径不存在之类的或者出现Error-000732错误?
解决办法:将相对路径“Database Connections/Connection to lish.sde”修改为绝对路径“C:/Users/gis/AppData/Roaming/ESRI/Desktop10.0/ArcCatalog/Connectionto lish.sde”即可,因为该问题有些机器有类似问题,有些机器没有,原因仍是不详。
4:在SDE新建或者是导入一个包含字段名称“AREA”的数据时,字段名会自动加前缀?
问题解答:该问题在ArcGIS9系列软件存在该情况,但是在ArcGIS10当中没有,原因不详!
5:在往创建好的RasterDataset里面LoadRaster时,如果加载整个Raster时,InputRaster提示红叉,必须将Raster对象双击打开为三个波段才能加载,如何才能加载整个Raster对象而不以波段形式加载呢?
问题分析:应该是用户在创建RasterDataset时默认选择的Rand Number是“1”造成的,将该值设定为“3”即可解决。
6:用户在使用Join来进行表与表的挂接(要素类与普通表),但是有些时候出现如果某个库在非Windows操作系统时就不能进行挂接,怎么解决?
问题分析:因为Join是使用Ole机制来进行挂接的,但是Windows操作系统默认有Ole的驱动,但是非Windows操作系统却没有,所以非Windows操作系统不支持Ole,进而不支持Join的使用,那么用户完全可以改变一下不同的方式使用sde命令来完成(sdetable -o create_view)来实现,效果是一样的,而且利用sde命令创建的视图是可以保存起来的,只读的,可以将该视图当作一个只读的要素类来对待。
sdetable命令参考:http://wenku.baidu.com/view/16c6362acfc789eb172dc8c2.html
7:在ArcCatalog上使用将ArcSDE数据导出PGDB,再导入进去,某些字段范围发生变化。
问题分析:以导入的字段为文本为例,因为PGDB也就是通常的Access,对Access的文本字段最大支持到255,大于该值变为备注字段,那么假如一个用户的ArcSDE文本字段长度为1000,那么导入到PGDB里面因为大于255所以转为备注字段,然后再倒入成ArcSDE里面,备注字段并不记录长度,直接将备注长度转换为CLOB(在Oracle数据库中文本大于2000的都会以CLOB存储),所以说,用户在数据的导入导出时如果不希望碰到该现象,请将导出的PGDB替换为FGDB即可。
8:在使用ArcMap或客户端开发(ArcGIS Engine),进行简单操作如放大地图等,出现以下现象:地图一片空白、提示“gsrvr.exe”错误或者提示“Network IO Error”错误?
问题分析:首先检查用户的数据库是不是和你ArcSDE的版本匹配,这个错误是典型的ArcGIS9.3/9.3.1和Oracle10.2.0.1(注意数据库的小版本号),这边建议数据库为Oracle10.2.0.3即可,那么如果没有这个原因的话,用户自定义开发的话注意资源的是否问题。
9:在使用ArcCatalog编辑过程中,保存数据时提示:“Create:An unexpected failure occurred”,ORA-20092:Maximum number of grids perfeature(8000) excessed.ORA-06512:在“SDE_ST_DOMAIN_METHODS”line 1487之类的。
问题分析:ArcGIS默认一个对象不能超过8000个格网,这是一个硬性规定,那么说明用户所编辑的图层的格网设置的太小或者用户所编辑的一个对象太大造成的。要么用户删除索引,重建索引,或者用户编辑格网值换一个大一点的格网值即可。
10:ArcMap导入数据报Ora-01480str绑定值的结尾 null 字符缺失。
问题解决:如果用户出现这个问题那么用户的机器配置应该是
操作系统:Windows Server 2003 /2008 Enterprise x64 SP2
Oracle 版本10.2.0.4.0 - 64bit
ArcSDE 版本: ArcSDE 9.3.1 for oracle10g64
DeskTop 版本: 9.3.1
矢量存储方式:ST_Geometry
这个没有办法,假如用户的配置完全满足以上配置,恭喜你,你太幸运了,这都被你碰上了,截至发稿ArcGIS9.3.1也没有解决该问题。
用户要么使用直连来导数据,要么使用BLOB存储而不选择ST_Geometry存储,估计选择第一种的人会更多吧。
11:ArcMap使用Identify图形,发现长度和面积都是0?
问题解析:该用户肯定使用了SDO_Geometry的几何数据存储方式,该结构根本不像ST_Geometry那种结构可以记录长度和面积,所以这样是正常的。
怎么对ArcSDE数据库的要素类进行批量重建空间索引
在我们遇到很多有关于性能的问题,我们一般建议用户重新常见空间索引,那么如果用户一个库里面有几十个甚至上百个空间索引,那么该怎么处理呢?
ArcGIS10.1版本
RebuildIndexes:(这个功能只有ArcGIS10.1才有的)
这个功能主要是对用户进行大范围数据编辑,在原有数据基础上做大量的数据加载或者数据删除后,为了提高数据性能,进行的操作。其实听到这里有点老生常谈,我们原来的方法也是一个图层一个图层的进行重建索引,但是这个功能可以批量的重建索引,而且及支持属性索引也支持空间索引,支持系统表以及版本的增量表的重建索引,比较方便。
ArcGIS10之前的版本
但是对ArcGIS10以及之前的版本并没有批量重建索引的办法,我们只能另辟蹊径了。
1:使用sde命令行的方法
我们可以使用sde命令,load_only_io和normal_io进行切换来进行空间索引的重建,具体请看帮助。
Switch between loadonly and normal I/O modes.
To modify a featureclass's input/output mode, use the load_only_io and normal_io operations.
You must be the ownerof the feature class to change it from normal I/O to load-only I/O mode.
It is recommendedthat you do not place a versioned feature class that uses binary storage inload only I/O mode because, when you switch back to normal I/O mode, thespatial index will be calculated on a versioned representation of the features.This representation may not match what is stored in the nonversioned f table towhich the index gets applied. If this is the case, an error is returned.
When the sdelayercommand is used to create a layer (i.e., if the register or add operations areused), the resultant feature class is automatically in normal I/O mode. The load-onlyI/O mode is provided to make bulk data loading processes more efficient. Useload-only mode when performing large inserts to avoid the continuous update ofthe feature class's indexes.
For feature classesthat use a spatial grid index (SDEBINARY, SDELOB, WKB_GEOMETRY, or featureclasses in DB2), if the grid fields are updated while the feature class is inload-only I/O mode, the spatial index is rebuilt with the new grid sizes whenyou reset the feature class to normal I/O mode. While rebuilding the spatialindex table, the feature class is inaccessible to other users. Note: You canchange the grid sizes while the feature class is in normal or load-only I/Omode. If you reset spatial indexes while the feature class is in normal I/Omode, the indexes on the spatial index table are dropped while the spatialindex is being re-created..
When the featureclass is in normal I/O mode, the envelope is automatically updated whenever afeature that extends the current envelope is added. The envelope is not updatedwhile the feature class is in load-only I/O mode but is recalculated to thefull extent when the feature class is reset to normal I/O mode.
These examples showthe parcels feature class being moved into load only mode then back to normalI/O mode.
sdelayer -oload_only_io -l victoria,parcels -u av -p mo -i esri_40
sdelayer -o normal_io-l victoria,parcels -u av -p mo -i esri_40
When the featureclass is returned to normal I/O mode, the spatial index table and databaseindexes are rebuilt. If the operation does not complete successfully for anyreason, the feature class is left in load-only I/O mode.
When a feature classis in load-only I/O mode, the unique index is removed from the feature class'sspatial column. When the index is absent, it is possible to enter nonuniquevalues into the spatial column with an application not created with the ArcSDEC- or Java application programming interface (API). Therefore, no applicationsbesides ArcSDE or applications created with the ArcSDE C- or Java API shouldever update the spatial column. Database administrators should be aware of theincreased vulnerability of the spatial column when the feature class is inload-only I/O mode.
我知道很多朋友肯定没有认真看上面的英文解释,但是没有关系,大家只需要知道,如果我们使用load_only_io模式,就是删除空间索引,我们使用normal_io模式就是创建空间索引就可以了。
那么知道了这两个模式,我们在对该模式做一个延伸介绍
注意:一般情况下,如果我们业务有变更的情况,比如我们插入一条记录,如果是使用ArcGIS客户端或者相关API进行操作,除了我们新添加一条记录外,我们还同步的对空间索引进行更新,但是如果我们业务上有批量更新的情况,那么我们除了变更数据表,而且我们还要同步的批量变更空间索引信息,这样对性能会有一些影响。那么我们就可以在批量变更之前,将数据切换到load_only_io模式,然后进行批量变更,等变更业务彻底完成之后,再切换到normal_io模式,以达到重建索引的目的。
那么对数据量比较多的要素类,我们可以使用sde命令编写批处理文件来对数据进行批量创建空间索引
@echo OFF
pause "按任意键开始"
sdelayer -o load_only_io -l quxian,shape -i 5151 -s192.168.220.165 -u sde -p sde
echo "图层quxian已经删除了空间索引"
sdelayer -o normal_io -l quxian,shape -i 5151 -s192.168.220.165 -u sde -p sde
echo "图层quxian已经创建了空间索引"
...
sdelayer -o load_only_io -l quxian1,shape -i 5151 -s192.168.220.165 -u sde -p sde
echo "图层quxian1已经删除了空间索引"
sdelayer -o normal_io -l quxian1,shape -i 5151 -s192.168.220.165 -u sde -p sde
echo "图层quxian1已经创建了空间索引"
pause "按任意键结束"
将以上数据保存为.bat文件,用的时候直接运行即可。
2:使用python脚本重建索引
如果大家留心会发现一个问题,虽然上面使用sde命令可以对要素类进行批量重建索引,但是它仍然需要用户指定特定的要素类名称,那么如果几十个甚至上百个要素类,对用户来说仍然是一个梦魇,那么我们使用python脚本就可以很轻松的实现这个功能。
我们使用Python脚本可以对某个SDE连接下的数据集或者要素类进行遍历,然后对遍历的要素类使用GP工具,该GP工具可以删除和重建空间索引,就是这么简单
from arcpy import *
env.workspace=r'DatabaseConnections\Connection to 192.168.100.111.sde'
for dataset inListDatasets():
for fc inListFeatureClasses("","ALL",dataset):
RemoveSpatialIndex_management(fc)
AddSpatialIndex_management(fc)
执行过程中,我们可以看到右边的信息框的执行过程。