為了提高空間查詢的性能,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)
執行過程中,我們可以看到右邊的資訊框的執行過程。