Oracle Spatial中的空間索引


轉自cryolite原文 Oracle Spatial中的空間索引

Oracle Spatial可對空間數據進行R-tree索引,每個空間圖層(Spatial Layer)的空間索引元信息都可以在USER_SDO_INDEX_METADATA視圖中找到。
具體的索引數據保存在MDRT字段開頭的表中, 每個空間圖層都會對應一個索引表(表的格式是MDRT_[...]$),空間索引表中的主要數據是MBR

通過空間索引元數據視圖(USER_SDO_INDEX_METADATA)可以查到每個空間圖層的空間索引名、空間索引數據表名、R-tree索引的根節點ROWID,R-tree的分支因子(又叫扇出fanout,即R-tree節點的最大子節點數)及其它相關信息。

索引的創建:
1. R-tree索引:
CREATE INDEX customers_sidx ON customers(location)
INDEXTYPE IS MDSYS.SPATIAL_INDEX;

2. 四叉樹索引:
CREATE INDEX customers_sidx ON customers(location)
INDEXTYPE  IS MDSYS.SPATIAL_INDEX
PARAMETERS ('SDO_LEVEL=8');

在Oracle Spatial中,四叉樹索引不如R-tree索引,因為:
1. 只能對二維非geodesic數據創建四叉樹索引;
2. 用戶自己要對四叉樹索引的參數進行調整,而R-tree索引的參數比較好調,也更自動。

關於四叉樹索引可以參考文檔: Oracle Spatial Quadtree Indexing


索引的效率:
1. 如果表空間指定為ASSM表空間(user_tablespaces表中segment_space_management為AUTO即是),索引中的LOB數據將是SECUREFILE LOB的,這比一般的BASIC LOB快。

2. 空間索引創建過程中會臨時產生許多工作表,創建完后會刪除這些工作表,這一過程中(大量不同大小的表的創建和刪除,其數據量大約是要索引的表的200-300倍)會使得表空間(tablespace)產生許多碎片從而影響表空間效率,可以為這些工作表指定獨立的表空間(即指定WORK_TABLESPACE)避免這一效率損失:
CREATE INDEX customers_sidx ON customers(location)
INDEXTYPE IS MDSYS.SPATIAL_INDEX
PARAMETERS ('WORK_TABLESPACE=SYSAUX');
注意工作表空間不得使用temporacy表空間。如果不指定工作表空間,缺省同要索引之表的表空間。

3. 要索引的geometry列如果都是相同形狀的幾何體(例如都是點),在創建索引時指定要索引空間圖層中的幾何體類型會提高查詢速度:

CREATE INDEX customers_sidx ON customers(location)  
INDEXTYPE IS MDSYS.SPATIAL_INDEX  
PARAMETERS ('LAYER_GTYPE=POINT');  

4. 如果需要在事務中進行大量的數據刪除/插入時可以考慮為空間索引設置SDO_DML_BATCH_SIZE參數,在事務中刪除/插入數據后並不會馬上就更新索引,而是在事務提交時、或者刪除/插入的數量達到某個批量值時統一索引更新,這個值(即SDO_DML_BATCH_SIZE)缺省為1000,對於大多數操作這個值足夠了。但是如果你的表在工作中會有大量刪除/插入操作,那么可以考慮將這個值設得更大以提高效率,代價是更多的內存和系統資源消耗:
CREATE INDEX  customers_sidx ON  customers(location)
INDEXTYPE  IS MDSYS.SPATIAL_INDEX
PARAMETERS ('SDO_DML_BATCH_SIZE=5000');

這個值最好設在5000-10000之間。

另一個提高大量插入刪除效率的方法是在大批量操作之前刪除索引,之后再重建索引

5. 對於一個有N個記錄的表創建空間索引:
1). R-tree的空間索引表大概需要100×3N個字節的存儲空間;
2). 在R-tree空間索引創建過程中,在臨時的數據表空間中需要200×3N到300×3N字節的額外存儲空間。
可以通過下列語句估算為一個空間圖層創建R-tree索引需要的存儲空間大小:
SELECT sdo_tune.estimate_rtree_index_size('SPATIAL', 'CUSTOMERS', 'LOCATION') sz FROM dual;
sz
-----------------
1

結果為1,表示
1). 索引數據需要1M字節的存儲空間,這是索引數據本身所需的存儲空間,此外在索引創建過程中2到3倍這個值的存儲空間;
2). 當創建空間索引時,指定session參數SORT_AREA_SIZE為這個值(1MB)會優化索引創建過程。


6. 如果使用SDO_NN空間操作符的效率問題
1) SDO_NN空間操作時,空間索引會遮蔽其它索引,因此不要期望使用SDO_NN空間操作符時在WHERE語句中加入更多的限制條件會加快查詢速度,這時對SDO_BATCH_SIZE參數進行微調有可能會提高查詢效率。
SELECT ct.id, ct.name, ct.customer_grade
FROM  competitors comp, customers ct
WHERE comp.id=1
AND ct.customer_grade='GOLD'
AND SDO_NN(ct.location,  comp.location)='TRUE'
AND ROWNUM<=5
ORDER BY ct.id;
盡管customer_grade字段有索引,但是這不會加快空間查詢的速度,執行時可能先找出10條最近的記錄,看是否是'GOLD'的,如果不是則找出接下來10條最近的記錄,。。。。。直到所有'GOLD'的用戶有5條為止。

如果預計5條'GOLD'用戶肯定在前100個最近的記錄里,則通過設置SDO_BATCH_SIZE參數為100可以加快查詢速度:
SELECT ct.id, ct.name, ct.customer_grade
FROM  competitors comp, customers ct
WHERE comp.id=1
AND ct.customer_grade='GOLD'
AND SDO_NN(ct.location,  comp.location, 'SDO_BATCH_SIZE=100' )='TRUE'
AND ROWNUM<=5
ORDER BY ct.id;

如果你不知道SDO_BATCH_SIZE該設為多少,就設為0,索引會在使用合適的內部值。

2) 限定SDO_NN返回的記錄數量會加快查詢的速度,這通過調整SDO_NUM_RES設置:
SELECT ct.id, ct.name, ct.customer_grade
FROM  competitors comp, customers ct
WHERE comp.id=1
AND SDO_NN(ct.location,  comp.location, 'SDO_NUM_RES=5')='TRUE' ;
效果與這個相同:
SELECT ct.id, ct.name, ct.customer_grade
FROM competitors comp, customers ct
WHERE comp.id=1
AND SDO_NN(ct.location,  comp.location)='TRUE'
AND ROWNUM<=5
ORDER BY ct.id;

空間索引與分區
上面建立的索引是全表范圍內的,是“全局”索引,在對數據庫表進行分區后,可以在每個分區上建立一個“本地(Local)”索引。
進行帶空間操作符的空間查詢時,Oracle會在每個分區的索引上進行查詢,然后將各個分區上的查詢結果匯集,最后將結果返回給用戶。因此,分區索引並不總能加快查詢速度。
分區也會影響查詢返回的結果:
例如SDO_NN操作符中的SDO_NUM_RES參數會指定符合條件的結果數量,但是如果是分區索引的話,則在每個分區上都得滿足此參數,如果有3個分區,那么最終返回的結果數量將是SDO_NUM_RES×3,而不是SDO_NUM_RES。

注:以上討論的分區是由限制的,只能是range分區,list分區和哈希分區都不行

空間索引與並行
創建索引時可以指定索引並行,例如:

 

CREATE INDEX customers_sidx ON customers(location)  
INDEXTYPE IS MDSYS.SPATIAL_INDEX  
PARALLEL [parallel_degree];  

 

 

 

並行參數parallel_degree是可選的,它定義了並行度,如果大於1,則索引創建時會並行進行。
但查詢時無法指定並行,查詢的並行實際上與數據庫表的分區有關,也就是說查詢會在每個分區上並行的進行。因此設定表的並行度並分區會提高使用空間索引的空間分析操作的性能。

ALTER TABLE customers PARALLEL 2 ; 

空間索引的重建
在對表進行大量(大約30%)刪除后,對空間索引進行重建可以提高未來數據的查詢效率:

ALTER  INDEX customers_sidx  REBUILD ; 

重建時也可以指定參數:

ALTER  INDEX customers_sidx REBUILD 

PARAMETERS ('layer_gtype=POINT'); 

注意:
1. ALTER INDEX是一個DDL語句,因此會導致當前事務的提交;
2. 空間索引重建是個耗時操作,它以排他鎖的方式阻止了在空間索引上的其它操作,從而造成相應空間查詢操作的阻塞,不過可以指定ONLINE關鍵字避免這種堵塞發生:

ALTER  INDEX customers_sidx REBUILD  ONLINE  
PARAMETERS ('layer_gtype=POINT');  

ONLINE重建索引的過程如圖所示:


重建的索引數據保存到新索引表上,重建時舊的索引表仍在,舊的查詢在舊索引上,因此重建過程不會影響正在進行的查詢,在新索引建好后再切換到新的索引表上。
要了解更多關於Oracle Spatial空間索引設計原理:
“Efficient Processing of Large Spatial Queries using Interior Approximations.” Proceedings of the 7th International Symposium on Spatial and Temporal Databases (SSTD), 2001.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM