本月技術會議專題為數據庫分區( SQL Server Partitioning ),主要講述為什麼要分區,在什麼情況下需要對數據進行分區,如何進行分區,分區表管理等內容。
一、 摘要
◆ 分區基礎知識
u SQL Server2005 分區
u 技術討論
u 會議決議
二、 分區技術知識
1、 為什麼要分區?
(1) scale up VS scale out
首先需要理解 scale up 和 scale out 的含義, scale up (向上擴展),即後端大型服務器以增加處理器等運算資源進行升級以獲得對應用性能的要求,提高硬件來提高數據處理及提高性能的一種方式。而 scale out (向外擴展)主要是指根據需求增加不同的服務器應用,依靠多部服務器協同運算,借負載平衡及容錯等功能來提高運算能力及可靠度的方式來提高數據處理和提高性能的一種方式。數據庫分區技術的應用則是 scale out 的體現。在此需要注意的是 Scale Out 方案始終面臨著數據集中的問題,即拆分過的數據在服務器邏輯體系中仍然是各自相對集中的而非無限隨意拆分。如果大量的邏輯放在數據庫服務器一端,數據庫服務器將會使得系統失去 Scale out 的能力和可能。因此,要保證 Scale out 的能力就必須保證數據庫只處理實質性的數據提交和不可避免的數據查詢,對於能夠避免的數據查詢和非實質性數據提交都應該想辦法予以避免。而具體的策略和方案相對沒有最優的方法。
(2) 避免昂貴的硬件開銷
使用分區技術處理大容量數據表,可以讓我們不必為了性能而購買昂貴的新服務器或者提高服務器硬件性能來提高性能。
(3) 使數據在一個合適的 Level 上管理
使用分區技術後,我們在對數據庫進行管理時,避免了面對 G 級別的數據量維護,只需要面對幾百兆或者幾十兆的數據,這樣使得我們面對數據庫管理時,處於一個合適的水平和級別,就能保證數據庫的高維護性,節約維護成本、資源
(4) 消除性能瓶頸,最小化維護成本
同樣使用分區技術後,客戶端對數據庫的操作也更容易更迅速,提高了數據庫的性能,對數據庫維護也相對簡單,比如說數據的備份、恢復等等。
2、 什麼情況下使用數據庫分區
(1) 大數據量表(管理 / 索引創建 / 索引重建 / 備份與恢復 / 擴充 )
面對大表,你首先遇到的一個管理的問題,因為數據量太大,管理非常復雜和麻煩。其次是索引,在大數據量表進行索引的建立、重建都會有可能因為超時而導致失敗。再次是表的維護,例如備份、恢復等有可能因為長時間的操作影響其他用戶的操作,最後還有一個表的擴充的問題,比如說擴充字段、鎖的升級。
在此,需要特別講述一下有關索引的問題,在 OLTP ( On-Line Transaction Processing )和 DSS ( Decision Support Systems )系統中,索引在上述兩種系統中的應用是不同,在 OLTP 系統中,可能我們需要很少的索引,而在 DSS 系統中,我們肯定需要大量的索引,同時我們在 OLTP 系統中對索引的重建和碎片整理需要經常性的去處理,而對於 DSS 系統,對於索引我們原則上只需要一次即可。
在備份與恢復的層面上分析, OLTP 是一個需要經常備份、存放很多關鍵數據的、需要保持高可用性的比較小型的 VLDB( VERY LARGE DATE BASE ) 的系統,而 DSS 是一個不需要經常備份、數據也非關鍵數據但需要保高可用的大型 VLDB 系統。
(2) 不同的訪問模式
一種訪問模式主要指聯機事務處理的方式,比如一些插入、更新、刪除等內容。另一種訪問模式主要是對數據庫的查詢、分析等操作,這些主要是一些 SELECT 的操作。
3、 分區策略( Partitioning StrategIEs )
(1) 垂直分區
垂直分區將一個表分為多個表,每個表包含較少的列。垂直分區包括兩種類型,即規范化和行拆分:
規范化是標准的數據庫進程,它刪除表中的多余列,並將這些列放置在通過主鍵和外鍵關系鏈接到主表的輔助表中。
行拆分將原始表垂直分成多個只包含較少列的表。拆分表內的每個邏輯行都與其他表內由 UNIQUE KEY 列(在所有已分區表中都相同)標識的相同邏輯行相匹配。例如,聯接每個拆分表內具有 ID 712 的行將重新創建原始行。
應該慎用垂直分區,因為分析多個分區中的數據時需要聯接表的查詢。如果分區過大,垂直分區還可能會影響性能。
(2) 水平分區
水平分區將表分為多個表。這樣,每個表包含的列數相同,但是行更少。例如,可以將一個包含十億行的表水平分區成 12 個表,每個小表表示特定年份內一個月的數據。任何需要特定月的數據的查詢都只引用相應的表。
具體如何將表進行水平分區取決於如何分析數據。您應將表進行分區,以便查詢引用的表盡可能少。否則,查詢時需要使用過多的 UNION 查詢來邏輯合並表,這會影響查詢性能。
4、 垂直分區案例
某個表存在記錄行為 1,600,000 rows 。此表有 47 個列, 4600Bytes/Row ,由於 SQL Server 本身系統限制一條記錄不能超過 8060Bytes ,所以我們一行記錄需要一頁,每條記錄浪費 3460Bytes ,這樣計算後整個表空間占用約 12G 。表內容如下所示:
表
表列數
( columns )
記錄行
( Rows )
每行大小
( Bytes/Row )
需要頁數
( Pages )
表大小
表 A
47
1,600,000
4600
1,600,000
12G
先對其進行垂直分區,假設此表為一個主鍵,我們將其分為三個表,分區標准如下表所示:
表
表列數
( columns )
記錄行
( Rows )
每行大小
( Bytes/Row )
需要頁數
( Pages )
表大小
表 1
14
1,600,000
1000
200,000
1.6G
表 2
18
1,600,000
1600
320,000
2.5G
表 3
17
1,600,000
2000
400,000
3.2G
合計:
7G
結果:節省了 5G 的空間,同時提高了性能。
另外在進行垂直分區的時候還需要注意一下幾點:
1 優化行的尺寸
因為 SQL Server 在對數據進行檢索的時候,是通過頁來取得的,這就要求我們盡量讓更多的記錄在一個頁上,才能保證更多的行在緩存中,這樣就保證了數據庫在進行 I/O 操作時,提高了性能。
另外,從鎖的方面分析,我們將列分區後,在進行操作時,列鎖定的是沒有分區表的幾個字段,而不是所有的字段,這就保證了另外兩個表不被鎖限制,也就降低了行鎖對數據庫並發用戶的影響。
2 使用方法
首先考慮將經常關聯的邏輯列進行分組,也就說將同一類屬性,經常放在一起進行查詢劃分為一個分組放到一個表中,從而減少表與表之間的交流和關聯;其次要考慮到那些列是只讀的,那些是 OLTP 環境下的列,這樣可以避免數據檢索時的重復性,提高性能。
5、 水平分區
水平分區創造出了更多的可管理的塊,同時減少的 DBA 對表的維護的影響,例如表索引管理、備份恢復等。另外,他減少的鎖對數據操作的影響,使得我們在對部分數據進行操作時,鎖僅僅在某一個部分進行,減少了鎖操作對數據庫資源的占用,從而提高了數據處理的效率。
三、 SQL Server2005 分區實現
1、 SQL Server2005 分區表和索引概念
物理分區,具有標准表和索引相關的所有的屬性和功能
大型表或索引經過分區後更容易管理,因為分區後可以更快速有效地管理和訪問數據子集,同時維護數據集合的完整性。通過分區,從 OLTP 向 OLAP 系統加載數據操作只需要幾秒鐘,同時由於對數據子集執行的維護操作只是針對所需數據而不是整個表,因此效率也得到了很大的提高。
已分區表和已分區索引的數據劃分為分布於一個數據庫中多個文件組的單元,數據俺水平方式分區,因此多組行映射到單個的分區中。單個索引或表的所有分區都必須位於同一個數據庫中。
在 SQL Server2005 中,數據庫中所有表和索引都視為已分區表和索引,即使這些表和索引只包含一個分區。
2、 分區設計
(1) 創建分區函數;
分區函數:分區函數定義如何根據某些列的值將表或索引的行映射到一組分區。(一張表最多有 1000 個分區)
(2) 創建分區方案;
分區方案:分區方案將分區函數指定的每個分區映射到文件組。(一個分區方案只能使用一個分區函數,但是,一個分區函數可以參與到多個分區方案)
(3) 在創建表和索引的時候,指定表或索引的分區方案。
3、 分區實現
(1) 創建分區函數
CREATE PARTITION FUNCTION partition_function_name ( input_parameter_type )
AS RANGE [ LEFT | RIGHT ]
FOR VALUES ( [ boundary_value [ ,...n ] ] ) [ ; ]
例句:
CREATE PARTITION FUNCTION myRangePF1( DATETIME ) AS RANGE RIGHT FOR VALUES ( '2007-12-21' , '2007-12-22' , '2007-12-23' , '2007-12-24' , '2007-12-25' , '2007-12-26' )
說明:指定當間隔值由 數據庫引擎 按升序從左到右排序時, boundary_value [ ,...n ] 屬於每個邊界值間隔的哪一側(左側還是右側)。如果未指定,則默認值為 LEFT 。
(2) 創建分區方案
CREATE PARTITION SCHEME partition_scheme_name
AS PARTITION partition_function_name
[ ALL ] TO ( { file_group_name | [ PRIMARY ] } [ ,...n ] )[ ; ]
例句:
CREATE PARTITION SCHEME mySchemePS1 AS PARTITION [myRangePF1] TO ( [PRIMARY], [FG1], [FG2], [FG3], [FG4], [FG5], [FG6], [FG7])
說明:如果創建的文件組少於要分區的指定的文件組,創建語句將執行失敗,如果創建的文件組大於要分區指定的文件組,那麼剩余的文件組將會做為下一次分區指定時使用,所以多出來的文件組也不會存在數據。
(3) 增加分區
ALTER PARTITION SCHEME partition_scheme_name
NEXT USED [ filegroup_name ] [ ; ]
例句:
ALTER PARTITION SCHEME MyRangePS1
NEXT USED test5fg;
說明:修改分區方案後,需要修改分區函數。
ALTER PARTITION FUNCTION partition_function_name()
{ SPLIT RANGE ( boundary_value )
| MERGE RANGE ( boundary_value ) } [ ; ]
例句:
ALTER PARTITION FUNCTION myRangePF1 ()
SPLIP RANGE ( 100);
(4) 合並分區
ALTER PARTITION FUNCTION myRangePF1 ()
MERGE RANGE (100);
(5) 創建分區表
CREATE TABLE PatitionTable( col1 int , col2 char ( 10))
ON MyRangePS1( col1);
(6) 創建分區索引
CREATE INDEX ix_Col2 ON PartitionTable( col2)
ON myRangePS1( col1);
CREATE INDEX ix_Col2 ON PartitionTable( col2)
說明:如果是根據分區依據列來創建索引,則不需要增加 On 後的內容。
(7) 分區信息查看
※ 使用 $PARTITION 函數
※ 訪問已分區表的分區子集中的所有行。
SELECT $PARTITION . myRangePF1( col1), count (*)
FROM PartitionTable
GROUP BY $Partition . myRangePF1( col1)
※確定包含特定分區鍵值的行位於哪個分區中?
SELECT $PARTITION . myRangePF1( col1)
4、 分區 DEMO
示例數據為 SQL Server2005 自帶的 AdventureWorks 數據庫,在這個數據庫中有兩個表 TransactionHistory (交易歷史信息表)和 TransactionHistoryArchive (交易歷史歸檔表), TransactionHistory 主要維護年度最新事務信息,而 TransactionHistoryArchive 保存歷史的事務信息。
TransactionHistory 設定為 12 個分區,存放了 03 年 9 月份到 04 年八月份的數據, TransactionHistoryArchive 分為 2 個區,存放了 03 年 9 月份之前和之後的數據,分區字段為 TransactionDate 。
每個月開始, TransactionHistory 當前最早的一個月的數據將被切換到 TransactionHistoryArchive 表中。需要注意的是,在這個操作中,如果不使用分區,而是使用導入導出或 INSERT 等語句進行數據的切換,是非常耗費資源和時間的,而采用分區,則避免了這個問題,因為在真正的操作中, SQL Server 並不是真正的將數據進行了遷移,而只是將源數據進行了切換,就是說數據的指針或者說數據資源表位置進行了修改,所以表分區之間的數據切換是瞬間的事情。
實現腳本:
ALTER TABLE [Production]. [TransactionHistory]
SWITCH PARTITION 1
TO [Production]. [TransactionHistoryArchive] PARTITION 2;
實現:見 SQL 腳本。
5、 條碼物流系統分區應用介紹
目前部門所規劃的 5 大產品之一條碼物流系統在開發中使用到了數據庫分區技術來改善數據庫性能,目前應用只是輪胎狀態表。
因為輪胎狀態表貫穿於整個條碼物流系統的各個工序和環節,也存放著大量的生產、質檢等數據,數據量非常巨大,在沒有進行分區時整個表的檢索經常出現檢索超時和客戶端死機的情況。
輪胎狀態表的分區主要依據於輪胎胎號,將 08 年之前的信息,按年分區,而 08 年之後的數據按照每 10 周進行分區,目前應用良好,對整個現場系統的應用和 WEB 系統的查詢性能都有了很大的改善。