程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> DB2 Spatial Extender 性能調優(1)

DB2 Spatial Extender 性能調優(1)

編輯:DB2教程

在幾乎所有的數據庫系統中,使運行在系統上的工作負載取得良好的性能是一項十分重要的任務。依靠 IBM DB2 Spatial Extender 的幫助,你可以在數據庫中將空間數據和你希望存儲的其他數據無縫的集成在一起。該擴展器提供了一組數據類型來表示空間信息。但是,DB2 Universal Database™(DB2 UDB)數據庫引擎還不能識別空間數據的確切屬性,並且也沒有提供內建的專用數據類型。所以,在為獲得最佳性能而調優空間數據庫時,需要比通常調優其他 DB2 UDB 數據庫時考慮更多的東西。本文介紹了在使用 DB2 Spatial Extender 時應該考慮的基本優化步驟,並對此作了詳細解釋。

簡介

DB2 UDB for Linux®、UNIX® 和 Windows® 從 7.1 版開始就提供了 DB2 Spatial Extender,用於支持空間數據的存儲、管理和修改(請參閱 參考資料 一節,下載 DB2 Spatial Extender)。可以用專用於空間信息及其屬性的結構來擴展已有的數據類型。

對於每個數據庫系統,無論它支持的功能有多好,如果不能為構建在系統上的應用程序提供所要求的性能,就毫無價值。因此,性能調優是一項非常關鍵的任務。這不僅是數據庫管理員的任務,也是應用程序開發人員的任務。DB2 UDB 已經提供了各種各樣的工具來幫助調優和監視系統,例如“Configuration Advisor”和“Design Advisor”。它們都可以通過 Control Center 訪問。

DB2 Spatial Extender 附帶了一個 Index Advisor,可以用它來優化包含空間數據的列上定義的索引。然而,索引調優只是性能調優的一部分,還可以通過調整其他一些參數來提高空間操作的性能,例如 inline length、聚集或表空間類型。在下面幾節中,我們將解釋其中每個參數,並展示它們相對於未經修改的系統的效果。我們在一台配有 1.2 GHz CPU 和 1 GB 物理內存的 IBM ThinkPad T30 上進行了評測。操作系統是 SUSE Linux 9.3,所有評測都基於帶 FixPak 9 的 DB2 UDB Version 8.2。請注意,我們沒有執行實際的基准測試,而是集中在單個更改上,這樣做只是為了展示特定調優選項的效果。您不能簡單地將結果中顯示的數據與其他系統進行比較。

基本性能調優

在任何性能調優過程中,第一步是為系統取得一個良好的基線。運行 DB2 Configuration Advisor 對該任務有所幫助(請參閱 參考資料 一節,獲得對 DB2 Configuration Advisor 的介紹和關於調優數據庫性能的信息)。可以從 Control Center 中通過右鍵單擊一個數據庫來啟動 Configuration Advisor,如圖 1 所示。

圖 1. 啟動 Configuration Advisor

您只需回答關於整個系統的一些簡單問題,在任何情況下您應該都知道這些問題。下面是這些問題的一個簡化列表,並提供了我們作出的選擇,後者以 斜體 顯示。從我們的選擇中可以看出,我們從一開始就關注性能。您具有的場景可能要求不同的選擇,例如對於鎖和恢復方面的問題就是如此。

您想將多少內存用於 DB2 實例? 809 MB(80%)。

您將執行更多的數據倉庫操作,還是執行更多的事務性操作? 都有。

您的事務是長還是短?一分鐘預期有多少事務? 較短的事務;一分鐘 60 個。

對您來說,更快的恢復與更快的事務哪個優先? 更快的事務。

數據庫已經包含了數據嗎? 還沒有包含數據。

本地和遠程連接的平均數量是多少? 平均 5 個本地連接,2 個遠程連接。

您想使用哪種隔離級別? Cursor stability (更少的鎖)。

在回答這組問題之後,Configuration Advisor 將提供對建議修改項的總結。現在您可以立即應用建議的修改,或將一個任務保存在任務中心。您應該檢查每一項修改,確定它們對系統是否有意義。如果想根據自己的需要進行調整,那麼可以在任務中心創建一個包含配置修改的任務,然後按照自己的需要修改任務腳本。在系統上運行 Configuration Advisor 之後可以得到如圖 2 所示的結果。最值得注意的是對缺省緩沖池大小的修改。增加緩沖池大小通常是提高系統整體性能的最重要的決定,因為它指定可以將多少數據緩存在內存中,從而減少對(較慢的)磁盤 I/O 的需要。

圖 2. Configuration Advisor 的建議

其他更改主要針對將可用內存劃分出一些必要的緩存,例如包緩存和編目緩存,或者調整短事務的設置(日志記錄和排序)。除了減少輔助日志文件的決定之外,所有更改都將被接受,不需任何人為干涉。我們將輔助日志文件的數量設為 10,以避免在空間導入操作期間可能發生的問題。取決於您的系統以及在那組問題中給出的答案,您得到的建議可能不同。

性能比較

首先在一個新安裝的系統上,在應用建議的配置更改之前,我們運行一組空間操作。這些操作的執行時間通過操作系統命令 time 或 DB2 的 db2batch 工具來測量。最後,我們清除數據庫,應用 DB2 Configuration Advisor 建議的配置,並重復相同的操作。為得到比較可靠的結果,我們多次執行導入操作和查詢,對測量到的時間取平均值。這些空間操作如下所示:

使用 Spatial Extender 命令行工具 db2se 從 DB2 Spatial Extender 附帶的第一張 Data & Maps CD 中將 shapefile 文件 europe/roads.shp 導入一個名為 ROADS 的表中。

執行一個空間操作,該操作使用一個簡單的空間查詢將這個表中所有的幾何圖形與一個固定的 linestring 進行比較。

在空間列上創建一個網格索引。

清單 1 展示了確切的步驟和它們產生的性能結果。可以在 下載 一節中找到 SQL 腳本 test_config_advisor.sql。

清單 1. 未調優的數據庫上的空間操作

$ time db2se import_shape testdb -fileName /home/stolze/europe/roads
    -srsName WGS84_SRS_1003 -tableName roads -createTableFlag 1
    -spatialColumn shape -typeName ST_LineString -idColumn id
    -commitScope 1500 -messagesFile /home/stolze/import.msg
GSE0000I The Operation was completed successfully.
real  
          2m19.086s
        
user  0m0.050s
sys   0m0.021s
$ db2batch -d testdb -f test_config_advisor.sql -i complete -s on
---------------------------------------------
Statement number: 1
SELECT id
FROM  roads
WHERE db2gse.ST_Intersects(shape, db2gse.ST_LineString(
     'linestring(10 50, 20 40)', 1003)) = 1
Prepare Time is:      0.000   seconds
Execute Time is:      1.248   seconds
Fetch Time is:       0.000   seconds
          Elapsed Time is:      1.248   seconds
        
---------------------------------------------
Statement number: 2
CREATE INDEX roads_grid_index ON roads(shape)
  EXTEND USING db2gse.spatial_index(0.27, 0.54, 1.6)
          Elapsed Time is:      25.503   seconds
        
---------------------------------------------

注意,測試系統使用的配置是次優的,因為導入的數據是從與數據庫和數據庫日志在同一個硬盤驅動器上的文件中讀取的。因而,讀操作與日志寫和緩沖池中的數據頁的寫操作之間存在競爭。可能需要將各種特定於磁盤的任務分配到不同的文件系統上。當使用 DB2 Spatial Extender 導入工具導入 shapefile 文件時,建議不要嘗試直接從 CD 裝載數據,而是先將它復制到一個硬盤上。CD-ROM 驅動器不是很適合讀 shapefile 文件的訪問模式,因此整個操作的速度會急劇降慢。

在應用了 Configuration Advisor 的建議之後,重復前面列出的步驟就產生了清單 2 中的結果。可以看到,僅僅是導入操作的性能就提高了 11%,查詢的速度快了 28%,甚至創建索引所花的時間也只有之前的 90%。所以不應當忽視最基本的性能調優。

清單 2. 調優後的數據庫上的空間操作

$ time db2se import_shape testdb -fileName /home/stolze/europe/roads
    -srsName WGS84_SRS_1003 -tableName roads -createTableFlag 1
    -spatialColumn shape -typeName ST_LineString -idColumn id
    -commitScope 1500 -messagesFile /home/stolze/import.msg
GSE0000I The Operation was completed successfully.
real  
          2m2.848s
        
user  0m0.051s
sys   0m0.027s
$ db2batch -d testdb -f test_config_advisor.sql -i complete -s on
---------------------------------------------
Statement number: 1
SELECT id
FROM  roads
WHERE db2gse.ST_Intersects(shape, db2gse.ST_LineString(
     'linestring(10 50, 20 40)', 1003)) = 1
Prepare Time is:      0.000   seconds
Execute Time is:      0.895   seconds
Fetch Time is:       0.000   seconds
          Elapsed Time is:      0.895   seconds
        
---------------------------------------------
Statement number: 2
CREATE INDEX roads_grid_index ON roads(shape)
  EXTEND USING db2gse.spatial_index(0.27, 0.54, 1.6)
          Elapsed Time is:      22.980   seconds
        
---------------------------------------------

DB2 內部對空間數據的處理

空間數據可能變得非常復雜,需要很多空間來存儲一個幾何圖形中各個點的信息。例如,表示整個美國的區域的幾何圖形由 60 個多邊形組成,總共有 198569 個點來定義那些多邊形。按照 Spatial Extender 內部格式,這個幾何圖形的完整定義要使用 0.9 MB 的磁盤空間(使用了壓縮)。如果幾何圖形按照 ESRI 幾何圖形格式編碼,那麼它實際上需要 3.1 MB 的磁盤空間(請參閱 參考資料 一節,了解關於 ESRI 幾何圖形格式的更多信息)。所有信息封裝在一個 ST_Geometry 值中,這意味著這個值在數據庫中也需要大約 1 MB 的磁盤空間。另一個例子是只表示一個點的空間值。對於 X 和 Y 維,我們只有用於兩個浮點值的 8 個字節。將一個點表示成 ST_Point 值會增加一些開銷,但是我們談論時仍然當作是幾個字節。

DB2 表中一個行中存儲的所有值的總大小不能超過表空間的頁寬。一個例外是大型對象(LOB),它最大可達 2 GB。DB2 支持的最大頁寬是 32K。所以存儲需要 1 MB 空間的幾何圖形需要類似於 LOB 的存儲機制。但總是為點數據使用那種機制就過分了。為了解決千差萬別的需求,DB2 實現了一種用於存儲空間數據(或通常的結構數據)的混合方法。如果一個空間值超過了某個大小(即所謂的 inline length),那麼這個值就被存儲為 BLOB。否則,這個值就存儲為 VARCHAR FOR BIT DATA 值。下一節 將詳細討論如何為空間列設置 inline length,以及通過更改設置可以獲得的好處。之後,我們討論 空間數據聚集,為 編寫空間 SQL 查詢、調優 空間網格索引 提供指南,最後我們解釋如果經常要修改數據,則建議使用哪種 表空間類型。

設置空間列的 inline length

在 上一節 中,我們解釋了 DB2 存儲需求多變的空間數據的內部機制。確定幾何圖形是存儲為 VARCHAR FOR BIT DATA 還是 BLOB 的決定因素就是所謂的 inline length,這個參數適用於任何表中的空間列。如果空間值的內部表示需要的字節數少於 inline length 設置中指定的值,那麼它將以 內聯(inline) 的方式存儲為 VARCHAR FOR BIT DATA。否則,這個值將被 大對象化(lobify),並在該表的 LONG 表空間中存儲為 LOB。

應該記住,以內聯方式存儲數據比以大對象化方式存儲數據要可取得多。原因是,內聯的數據當作 VARCHAR FOR BIT DATA 對待。這個值與同一行中所有其他屬性一起存儲在一個數據頁中。一旦數據存儲在那樣一個頁上,那一頁將通過緩沖池來訪問,這樣可以利用先進的緩存技術,從而盡量避免文件 I/O。而對於 LOB 則截然不同,它總是直接從磁盤讀取。

所以經驗法則非常簡單:將 inline length 設置得盡可能高,以便讓盡可能多的空間值以內聯方式存儲。當然,實際情況並不像看上去的那麼簡單。高的 inline length 值告訴 DB2 空間值實際上可以在單獨一行中占用很多字節。每一行的最大大小要受到針對表定義的頁寬和屬性(列)的限制。例如,如果有一個頁寬為 4 KB(4096)的表空間,那麼一行的最大大小不能超過 4005 字節(請參閱 參考資料 一節,了解關於 SQL 限制的更多信息)。如果這個表有一個不能為空的 INTEGER 列和一個可以為空的 VARCHAR(100) 列,再加上一個空間列,那麼最多可以將 inline length 設置為 4005 - 6 - 4 - (1+2+100) - 1 = 3891,其中 6 個字節用於行的前綴,4 個字節是 INTEGER 列需要的空間,(1+2+100) 個字節是為 VARCHAR(100) 預留的,最後 1 個字節用於空間列的 NULL 指示符(請參閱 參考資料 一節,找到關於數據庫對象和 CREATE TABLE 語句的一本書)。可以看到,其他列的長度和 inline length 實際上是相互競爭的。為了進一步增加 inline length,可以將表放在頁寬為 8K、16K 甚至 32K 的表空間上。這樣,對於之前的例子,就可以分別將 inline length 設為 7987、16179 或 32563 字節。

inline length

當在數據庫中創建一個新的結構類型時,DB2 將根據類型定義中指定的屬性計算那個數據類型的缺省 inline length。可以在系統編目視圖 SYSCAT.DATATYPES 的 INLINE_LENGTH 列上找到一個結構類型的缺省 inline length。如果在 CREATE TABLE 或 ALTER TABLE ... ADD COLUMN ... 語句中定義表的列時沒有顯式地指定 inline length,那麼將沿用缺省值。

可以使用 ALTER TABLE ... ALTER COLUMN ... SET INLINE LENGTH ... 語句修改(增加)已有空間列的 inline length。除非通過 REORG TABLE 語句 加 LONGLOBDATA 選項重組存儲在表中的數據,否則這種修改只影響 DB2 編目和隨後的數據修改。如果值的大小小於新的 inline length,那麼這個重組過程將把大對象化的空間值轉換成內聯值。

選擇適當的 inline length

在將所有空間數據存儲到 32K 的表空間上並且將 inline length 設置成盡可能大的值之前,應該首先分析您的數據實際上有多大以及其他參數可能對頁寬產生的影響。如果只有 ST_Point 值,那麼每個點將需要最多 245 字節的物理存儲,如清單 3 所示。在這種情況下,甚至 減少 inline length 更有幫助,因為可以使用更小的頁寬和/或在表中使用更多的列。但是要注意,ALTER TABLE 語句只允許增加 inline length。如果想使用更小的值,那麼必須在創建表的時候指定。Spatial Extender 導入過程允許顯式地為空間列指定 inline length。

在結構類型中嵌套 LOB

雖然 points 屬性被定義為 BLOB,但是 DB2 並不會單獨地存儲它。相反,整個幾何圖形信息(包括 BLOB 數據)都存儲在一起 —— 至於存儲為內聯值還是大對象化值,則取決於列的 inline length。結構類型的實現使所有屬性值並置到一個二進制流中,任何添加的必要的元信息和產生的二進制流在物化(也就是存儲到一個表中)的時候,或者存儲為內聯值,或者存儲為大對象化值。

這種方法使任何處理 LOB 的應用程序可以以內聯方式存儲短的 LOB 值,並利用 DB2 的緩沖池。

清單 3 展示了如何計算每個幾何圖形在以內聯方式存儲時需要多少磁盤空間。我們假設所有幾何圖形都存儲在一個名為 SPATIAL_DATA 的表的 GEOMETRY 列中。第一個查詢使用 LENGTH 函數。該函數顯示以內聯方式存儲的值的寬度。如果是大對象化的值,那麼它顯示引用實際值的定位符的寬度。所以只有知道所有空間值都是內聯值時,才可以放心地使用該函數。因此,下面的查詢根據空間數據類型的屬性來計算數據的寬度。關於屬性的信息可以從 DB2 編目視圖 SYSCAT.DATATYPES 和 SYSCAT.ATTRIBUTES 獲得。如果空間數據是使用結構類型實現的,那麼在 SQL Reference 中關於 CREATE TYPE 語句的解釋中提到的判斷結構類型值寬度的法則同樣適用(請參閱 參考資料 一節,了解關於 CREATE TYPE 語句的信息)。具體地說,ST_Geometry 類型定義 16 個屬性,它的子類型都沒有添加自己的屬性。除了三個屬性外,所有屬性都是所謂的 短屬性。其中兩個非短屬性 anno_text 和 ext 沒有被使用,第三個非短屬性 points 包含內部編碼為 BLOB 的幾何圖形信息。除了實際的數據外,DB2 需要維護強制的 null 指示符(1 個字節)和長度信息(4 個字節)。因此,幾何圖形的大小可以通過公式 “32 + 16*10 + 5 + LENGTH(points) = 197 + LENGTH(points)” 得出。

清單 3. 幾何圖形的空間需求

-- maximum space requirement for spatial point data
CREATE TABLE test ( p db2gse.ST_Point INLINE LENGTH 3800 )@
INSERT INTO test VALUES ( db2gse.ST_Point(
               1234567890123456, 1234567890123456,
               1234567890123456, 1234567890123456, 0) )@
SELECT LENGTH(p) FROM test@
1
-----------
    245
 1 record(s) selected.
-- determining the size of all geometrIEs in a table
SELECT 197 + LENGTH(geometry..points)
FROM  spatial_data@
-- calculating #geometries that would be stored inline/lobifIEd
-- for a given inline length
SELECT SUM(inline) AS inline, COUNT(*) - SUM(inline) AS lobifIEd
FROM  ( SELECT CASE
          WHEN 197 + LENGTH(geometry..points) <= <inline_length>
          THEN 1
          ELSE 0
        END
     FROM  spatial_data ) AS t(inline)@

性能比較

為了演示小的 inline length 與大的 inline length 的效果,我們首先將 shapefile 文件 europe/roads.shp 導入到一個 inline length 為 292 的表中。這是 DB2 允許的最小值。接著運行一個 SQL 腳本,該腳本確定有多少幾何圖形以內聯方式存儲,有多少幾何圖形必須以大對象化的方式存儲。然後測量執行一個簡單空間查詢的時間,並顯示在執行期間產生的語句快照的一個摘錄,以揭示影響性能的最突出的因素。整個過程在 inline length 為 2000 的情況下再重復一遍,2000 這個值足以導致那個 shapefile 文件中的所有幾何圖形都以內聯方式存儲。下載 一節中包含了我們運行 db2batch 時使用的腳本 test_inline_length.sql。

清單 4. 不同 inline length 設置的效果

$ time db2se import_shape testdb -fileName /home/stolze/europe/roads
    -srsName WGS84_SRS_1003 -tableName roads -createTableFlag 1
    -spatialColumn shape -typeName ST_LineString -inlineLength 292
    -idColumn id -commitScope 1500
GSE0000I The Operation was completed successfully.
real  
          3m15.604s
        
user  0m0.050s
sys   0m0.026s
$ db2batch -d testdb -f test_inline_length.sql -i complete -s on
---------------------------------------------
Statement number: 1
SELECT SUM(inline) AS inline_storage,
    COUNT(*) - SUM(inline) AS lobifIEd_storage
FROM  ( SELECT CASE
          WHEN 197 + LENGTH(shape..points) <=
              ( SELECT inline_length
               FROM  syscat.columns
               WHERE colname = 'SHAPE' AND
                  tabname = 'ROADS' )
          THEN 1
          ELSE 0
        END
     FROM  roads ) AS t(inline)
INLINE_STORAGE LOBIFIED_STORAGE 
-------------- ----------------
     89595      21384
---------------------------------------------
Statement number: 2
SELECT id
FROM  roads
WHERE db2gse.ST_Intersects(shape, db2gse.ST_LineString(
     'linestring(10 50, 20 40)', 1003)) = 1
Prepare Time is:      0.000   seconds 
Execute Time is:      0.854   seconds 
Fetch Time is:       0.000   seconds 
          Elapsed Time is:      0.855   seconds
        
Buffer pool data logical reads        = 16818
Buffer pool index logical reads       = 19731
Direct reads                 = 3088
          Direct read requests             = 1544
        
Direct read elapsed time (ms)        = 18
---------------------------------------------
$ db2 "DROP TABLE roads"
$ time db2se import_shape testdb -fileName /home/stolze/europe/roads
    -srsName WGS84_SRS_1003 -tableName roads -createTableFlag 1
    -spatialColumn shape -typeName ST_LineString -inlineLength 2000
    -idColumn id -commitScope 1500
GSE0000I The Operation was completed successfully.
real  
          1m57.212s
        
user  0m0.049s
sys   0m0.027s
$ db2batch -d testdb -f test_inline_length.sql -i complete -s on
---------------------------------------------
Statement number: 1
SELECT SUM(inline) AS inline_storage,
    COUNT(*) - SUM(inline) AS lobifIEd_storage
FROM  ( SELECT CASE
          WHEN 197 + LENGTH(shape..points) <=
              ( SELECT inline_length
               FROM  syscat.columns
               WHERE colname = 'SHAPE' AND
                  tabname = 'ROADS' )
          THEN 1
          ELSE 0
        END
     FROM  roads ) AS t(inline)
INLINE_STORAGE LOBIFIED_STORAGE 
-------------- ----------------
    110979        0 
---------------------------------------------
Statement number: 2
SELECT id
FROM  roads
WHERE db2gse.ST_Intersects(shape, db2gse.ST_LineString(
     'linestring(10 50, 20 40)', 1003)) = 1
Prepare Time is:      0.000   seconds
Execute Time is:      0.792   seconds
Fetch Time is:       0.000   seconds
          Elapsed Time is:      0.792   seconds
        
Buffer pool data logical reads        = 17337
Buffer pool index logical reads       = 19731
Buffer pool index physical reads       = 0
          Direct reads                 = 2
        
Direct read requests             = 1
Direct read elapsed time (ms)        = 0
---------------------------------------------

從結果中可以看出,對於重要操作,較大的 inline length 可以增加 40% 的速度,對樣本數據的查詢也快了 7%。這兩種差異的底層原因是,當使用較小的 inline length 時,有超過 20000 個幾何圖形(大約 20% 的數據)以大對象化的方式存儲。DB2 直接從磁盤讀(寫) LOB 數據。而在第二種場景中,大部分的直接讀是不需要的,因為可以用存儲在緩沖池中的內聯數據來滿足查詢。注意,大對象化的數據所占的 20% 的比例實際上不算很壞。如果由於稍微復雜一點兒的幾何圖形導致更多的數據不能以內聯方式存儲,那麼這裡演示的差異還要大大增加。

聚集空間數據

根據某個屬性聚集數據是一種常見的、也是非常有用的技術,這種技術可以物理地組織一個表的數據。通過對底層的觀察可以發現,具有相似值的數據常常一起被訪問。所以,可以將類似的數據存儲在接近的位置,使得對那些數據的訪問不必分散到表空間中很多不同的頁上,而是分布在臨近的幾個頁上。根據空間數據的空間屬性或幾何圖形間的距離聚集空間數據是很自然的。空間查詢是展示局部數據訪問(換句話說,現實中臨近的幾何圖形常常被一起訪問)的最好例子之一。例如,如果您看一個城市的街道地圖,那麼很可能對那個城市的所有街道感興趣,而對地區另一邊某個其他城市的街道不感興趣。所以在物理上將那個城市的一些行存儲在相鄰的位置的確很有意義。

在 DB2 中建立數據聚集屬性的方法是根據一個索引對表進行重組。然而,如果由於空間索引的復雜性質導致 DB2 REORG TABLE 命令不理解空間索引,事情就不會那麼容易了。關於這個問題有一個容易的方法,即使用一個列,這個列的值是根據涉及的圖形計算的。這個列上聲明的數據類型必須保證 DB2 能在這個列上創建一個本地 B- 樹索引。這裡使用空間填充曲線來保存空間和拓撲屬性(請參閱 參考資料 一節,找到 H. Sagan 撰寫的書籍)。我們在幾何圖形上取一個點,即形心點, 計算那個點在空間填充曲線上的值,並將結果存儲在一個附加的列中。最後,在附加列上創建一個索引,並根據那個索引對表進行重組。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved