分區表
通常單表數據量到達百萬級別就需要使用分庫、分區、分表操作來達到一個均衡的效果。
新創建的數據表的數據會默認存在數據庫的.mdf文件里,而分區表數據會按照指定的分區方案(Scheme)存儲在不同文件里。
優點:
- 均衡I/O: 分區文件映射到不同磁盤可以平衡I/O效率,改善系統性能
- 增加可用性:單個分區出現問題,其余分區正常使用。
- 提高檢索速度:按分區可避免全表掃描
缺點:
- 管理難度提升,需要管理的對象:Group列表、File列表、Scheme、Func、定時任務
以下流程最終效果為:一個表對應一個方案;一個方案對應一個函數對應多個文件組;一個文件組對應一個文件
創建流程:
1)新建分區文件組
2)新建分區文件
3)新建分區函數與分區方案
4)新建表/綁定現有表
創建分區表 (T_sql方式)
1)創建分區文件組
一個文件組對應一個文件,那為什么還需要文件組這個概念存在?
DBA:文件組是數據庫一個負載均衡的維度,在這里體現不出優點來
-- 創建文件組
ALTER DATABASE [db_hmTest] ADD FILEGROUP db_hmTest_OrderGroup202105;
ALTER DATABASE [db_hmTest] ADD FILEGROUP db_hmTest_OrderGroup202106;
ALTER DATABASE [db_hmTest] ADD FILEGROUP db_hmTest_OrderGroup202107;
ALTER DATABASE [db_hmTest] ADD FILEGROUP db_hmTest_OrderGroup202108;
2)創建文件
每個數據庫都有個默認的文件組【PRIMARY】
-- 創建文件
ALTER DATABASE [db_hmTest] ADD
FILE(NAME=N'db_hmTest_Order202105',FILENAME=N'D:\DB\Partition\db_hmTest_Order202105.mdf',SIZE=5MB,FILEGROWTH=1MB,MAXSIZE=UNLIMITED)
TO FILEGROUP [db_hmTest_OrderGroup202105]
ALTER DATABASE [db_hmTest] ADD
FILE(NAME=N'db_hmTest_Order202106',FILENAME=N'D:\DB\Partition\db_hmTest_Order202106.mdf',SIZE=5MB,FILEGROWTH=1MB,MAXSIZE=UNLIMITED)
TO FILEGROUP [db_hmTest_OrderGroup202106]
ALTER DATABASE [db_hmTest] ADD
FILE(NAME=N'db_hmTest_Order202107',FILENAME=N'D:\DB\Partition\db_hmTest_Order202107.mdf',SIZE=5MB,FILEGROWTH=1MB,MAXSIZE=UNLIMITED)
TO FILEGROUP [db_hmTest_OrderGroup202107]
ALTER DATABASE [db_hmTest] ADD
FILE(NAME=N'db_hmTest_Order202108',FILENAME=N'D:\DB\Partition\db_hmTest_Order202108.mdf',SIZE=5MB,FILEGROWTH=1MB,MAXSIZE=UNLIMITED)
TO FILEGROUP [db_hmTest_OrderGroup202108]
3)創建分區函數與分區方案
按照以下設置,效果為:
db_hmTest_OrderGroup202105文件保存范圍: (-∞,2021-06-01T00:00:000)
db_hmTest_OrderGroup202106文件保存范圍: [2021-06-01T00:00:000,2021-07-01T00:00:000)
db_hmTest_OrderGroup202107文件保存范圍: [2021-07-01T00:00:000,2021-08-01T00:00:000)
db_hmTest_OrderGroup202108文件保存范圍: [2021-08-01T00:00:000,+∞)
-- 創建分區函數
CREATE PARTITION FUNCTION HmTest_Order_Func(DATETIME2(2))
AS RANGE RIGHT FOR
VALUES(N'2021-06-01T00:00:00.000',N'2021-07-01T00:00:00.000',N'2021-08-01T00:00:00.000')
-- 創建分區方案
CREATE PARTITION SCHEME HmTest_Order_Scheme AS PARTITION HmTest_Order_Func
TO([db_hmTest_OrderGroup202105],[db_hmTest_OrderGroup202106],[db_hmTest_OrderGroup202107],[db_hmTest_OrderGroup202108])
4)新建表/綁定現有表
通常情況下id作為表的主鍵,但在這里是按add_time作為分區關聯列的。所以我選的方案是用id+add_time做聯合主鍵-聚合索引
-- 創建表並綁定分區方案
IF OBJECT_ID(N'[dbo].[t_order]',N'U') IS NOT NULL
DROP TABLE [t_order];
CREATE TABLE [t_order](
id INT NOT NULL,
product NVARCHAR(200) NOT NULL,
size FLOAT NOT NULL,
add_time DATETIME2(2) NOT NULL
PRIMARY KEY(id,[add_time])
) ON HmTest_Order_Scheme([add_time])
-- 綁定現有表
CREATE CLUSTERED INDEX PK_hmTest_order_id_addTime ON
[dbo].[t_order_01]([id],[add_time])
WITH(SORT_IN_TEMPDB=OFF,DROP_EXISTING=OFF,ONLINE=OFF) ON
[HmTest_Order_Scheme]([add_time]);
存儲過程 - 動態分區
通常做法是,數據庫會做定時任務,每月第一天執行下面的存儲過程,每月產生一個文件組和文件
-- 新建存儲過程,每月新增一個文件組
CREATE PROCEDURE [Prop_HmOrder_AutoExtend_Partition]
AS
BEGIN
DECLARE @FilePath VARCHAR(100), --文件路徑
@FileName VARCHAR(100), --文件名稱
@FileSize VARCHAR(100), --文件大小
@FileGrowth VARCHAR(100), --文件增長
@FileMaxLimit VARCHAR(100), --文件最大限制
@FileGroupName VARCHAR(100), --文件組名稱
@Database VARCHAR(100), --操作數據庫
@CurrentDateTimeByYearAndMonth VARCHAR(100), --當前時間,年月
@SchemeName VARCHAR(100), --分區方案名稱
@PartitionName VARCHAR(100), --分區函數名稱
@sql VARCHAR(400); -- 賦值文件屬性
SET @FileSize = '5MB';
SET @FileGrowth = '1MB';
SET @FileMaxLimit = 'unlimited';
SET @CurrentDateTimeByYearAndMonth = LEFT(CONVERT(VARCHAR(30), GETDATE(), 112), 6);
SET @FileName = 'db_hmTest_Order' + @CurrentDateTimeByYearAndMonth;
SET @FilePath = 'D:\DB\Partition';
-- 賦值數據庫屬性
SET @Database = 'db_hmTest';
-- 賦值文件組屬性
SET @FileGroupName = 'db_hmTest_OrderGroup' + @CurrentDateTimeByYearAndMonth;
-- 賦值分區屬性
SET @SchemeName = 'HmTest_Order_Scheme';
SET @PartitionName = 'HmTest_Order_Func()';
-- 創建文件組
SET @sql = 'alter database ' + @Database + ' add filegroup ' + @FileGroupName + '';
EXEC (@sql);
-- 創建文件,並綁定文件組
SET @sql = 'alter database ' + @Database + ' add file (name=''' + @FileName + ''',' + 'filename=''' + @FilePath + '\'
+ @FileName + '.mdf'',' + 'size = ' + @FileSize + ',' + 'filegrowth = ' + @FileGrowth + ',' + 'maxsize = '
+ @FileMaxLimit + '' + ')' + 'to filegroup ' + @FileGroupName;
EXEC (@sql);
-- 修改分區方案
SET @sql = 'alter partition scheme ' + @SchemeName + ' next used ' +
@FileGroupName + '';
EXEC (@sql);
-- 修改分區函數
SET @sql = 'alter partition function ' + @PartitionName + ' split range (N''' +CONVERT(VARCHAR(30), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0), 120)+''')'
EXEC (@sql);
END;
GO
雜項列表
1)db_hmTest_OrderGroup202108會包含[2021-08-01T00:00:000,+∞)。后期動態新增文件組時,數據庫會自動把[2021-09-01T00:00:000,+∞)里的數據分配到db_hmTest_OrderGroup202109
2)表一定要建主鍵,不然檢索速度很慢
3)通過時間字段做分區關聯列時,其它字段不可單獨做聚合索引
