資料庫單表數據量太大可能會導致資料庫的查詢速度大大下降(感覺都是千萬級以上的數據表了),可以採取分區分表將大表分為小表解決(當然這隻是其中一種方法),比如數據按月、按年分表,最後可以使用視圖將小表重新併為總的虛擬表,其實並不影響上層程式的使用(程式也許都不知道分表了)。 主要步驟: 1、新建文件組, ...
資料庫單表數據量太大可能會導致資料庫的查詢速度大大下降(感覺都是千萬級以上的數據表了),可以採取分區分表將大表分為小表解決(當然這隻是其中一種方法),比如數據按月、按年分表,最後可以使用視圖將小表重新併為總的虛擬表,其實並不影響上層程式的使用(程式也許都不知道分表了)。
主要步驟:
1、新建文件組,將數據表文件保存路徑指向相應文件組(應將文件組和文件放入不同的磁碟中,甚至不同伺服器形成分散式資料庫,因為數據的讀取瓶頸很大程度在於磁碟的的讀寫速度,多個磁碟存放一個表可以負載均衡)
2、設置分區函數(聲明分區的標準)
3、設置分區方案(即哪些區域使用哪個分區函數,形成完整的分區方案)
4、給新表或現有表設置分區方案
5、建立視圖
詳細步驟(看需求可選):
一、資料庫狀態備份和恢復
USE master -- 備份 BACKUP DATABASE AdventureWorks TO DISK = 'AdventureWorks.bak' WITH FORMAT ---- 恢復 RESTORE DATABASE AdventureWorks FROM DISK = 'AdventureWorks.bak' WITH REPLACE GO
二、文件組和文件操作
添加文件組
USE [master]
GO
ALTER DATABASE ZHH ADD FILEGROUP [文件組名稱]
Go
添加文件並把其指向指定文件組
USE master; GO ALTER DATABASE 資料庫名 ADD FILE( NAME=N'文件名', FILENAME='存放路徑', //如:E:\201109.NDF(精確到文件名)文件組存放與不同磁碟可以提高IO讀寫效率(多個磁頭併發) SIZE=3MB, MAXSIZE=100MB, FILEGROWTH=5MB )TO FILEGROUP [文件組名] Go
修改文件(可選)
USE master; GO ALTER DATABASE 資料庫名 MODIFY FILE (NAME = 文件名, SIZE = 20MB); //可以修改所有屬性,列舉即可 GO
刪除文件(可選)
ALTER DATABASE 資料庫名 REMOVE FILE [文件組名]
三、分區函數和分區方案
分區函數
用於規範如何分區的標準,如已哪列進行為標準分區、分區的方式(按時間、ID等)、分區的具體界限(一般來說,界限指標數要比分區數少1,一刀則有兩段)
USE 資料庫名 GO CREATE PARTITION FUNCTION 分區函數名 (指標列的數據類型) //如:datetime、int AS RANGE RIGHT //右邊界切分,預設為LEFT FOR VALUES (劃分界限) //如時間劃分('2003/01/01', '2004/01/01'),兩個時間界限可劃分出三個分區 GO
分區方案
用於將已經建立好的分區函數組織成完整的方案,為每個分區分配存儲位置
Use 資料庫名 go create partition scheme 分區方案名 as partition 分區函數 to(文件組1,文件組2,文件組3,...) //註意分區數要與實際分區一致 go
在原有的基礎上添加分區(可選)
use 資料庫名 go alter partition scheme ps_OrderDate next used [FG4] //修改分區方案ps_OrderDate,定義新新分區使用FG4文件組 alter partition function pf_OrderDate() split range('2005/01/01') //修改分區函數pf_OrderDate,在末尾添加界限'2005/01/01' go
為現有表設置分區方案(可選)
//為AutoBench表的InsertTime列創建新聚集索引,並綁定Scheme_DateTime分區方案 CREATE CLUSTERED INDEX IX_CreateDate ON AutoBench (InsertTime) ON Scheme_DateTime (InsertTime)
註:如原來主鍵有聚眾索引要將其改為非聚集索引,才可添加新聚眾索引
//刪除原主鍵上的聚集索引PK_Product ALTER TABLE Product DROP CONSTRAINT PK_Product //重新創建主鍵非聚集索引PK_Product ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY NONCLUSTERED (ProductID ASC)
上面語句也可直接在索引屬性中將聚集改為非聚集
為新建表設置分區方案(可選)
//創建表格Order,並設置Scheme_DateTime分區方案,指標列為OrderDate CREATE TABLE [Order] ( OrderID INT IDENTITY(1,1) NOT NULL, UserID INT NOT NULL, TotalAmount DECIMAL(18,2) NULL, OrderDate DATETIME NOT NULL ) ON Scheme_DateTime (OrderDate) 查詢分區數據
四、其他操作
查詢分區數據
$partition函數--為任何指定的分區函數返回分區號,一組分區列值將映射到該分區號中
語法: [ database_name. ] $PARTITION.partition_function_name(expression)
參數: database_name 包含分區函數的資料庫的名稱。
partition_function_name 對其應用一組分區列值的任何現有分區函數的名稱。
expression 其數據類型必須匹配或可隱式轉換為其對應分區列數據類型的表達式。 expression 也可以是當前參與partition_function_name 的分區列的名稱。
返回類型: int (分區號)
//篩選使用Function_DateTime作為分區函數的AutoBench表,以InsertTime作為指標列的第二個分區的所有數據 select * from AutoBench WHERE $PARTITION.Function_DateTime(InsertTime) = 2
合併分區
//刪除Sales資料庫下的分區函數pf_OrderDate中的'2003/01/01'界限,以次界限劃分的兩個分區合併,分區號一次減1 use Sales go alter partition function pf_OrderDate() merge range('2003/01/01') go
查看系統視圖
select * from sys.partition_functions //分區函數 select * from sys.partition_range_values //分區方案 select * from sys.partition_schemes //邊界值點
五、自動分區
可以採用SQL Server代理中的作業定期自動執行分區腳本,實現自動分區(如每月結束自動執行按月分區的操作)
自動分區測試腳本
DECLARE @fileGroupName VARCHAR(20), --文件組名(格式為:FG+@Month) @fileName VARCHAR(20), --文件名(格式為:F+@Month) @filePath VARCHAR(100), --文件存放路徑(格式為:存放目錄路徑+@fileName.ndf) @dataBaseName VARCHAR(20), --資料庫名 @Month VARCHAR(10), --當前時間年月(格式為:yyyymm) @schemeName VARCHAR(20), --分區方案名 @partFunctionName VARCHAR(20), --分區函數名 @limit VARCHAR(10) --分區界限(以時間分區則為時間字元串,格式為:mm/dd/yyyy) SET @fileGroupName='FG201805' SET @Month=CONVERT(varchar(10),GETDATE(),112) SET @fileName=N'F201805' SET @filePath='C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\F201805.ndf' SET @dataBaseName='Chassis' SET @schemeName='Scheme_DateTime' SET @partFunctionName='Function_DateTime' SET @limit=CONVERT(varchar(10),GETDATE(),101) --語句要指明需要操作的資料庫 if exists(select * from Chassis.sys.filegroups where name=@fileGroupName) begin print '文件組存在,不需添加' end else begin exec('ALTER DATABASE '+@dataBaseName+' ADD FILEGROUP ['+@fileGroupName+']') print '新增文件組'+@fileGroupName end if exists(select * from Chassis.sys.database_files where [state]=0 and (name=@fileName or physical_name=@filePath)) begin print 'ndf文件存在,不需添加' end else begin exec('ALTER DATABASE '+@dataBaseName+' ADD FILE(NAME ='''+@fileName+''',FILENAME = '''+@filePath+''')TO FILEGROUP ['+@fileGroupName+']') print '添加文件'+@fileName+'至文件組'+@fileGroupName end if exists(select * from sys.partition_schemes where name=@schemeName) begin exec('alter partition scheme '+@schemeName+' next used ['+@fileGroupName+']') print '修改分區方案,指定下一分區的文件組' end else begin print '分區方案不存在' end if exists(select * from sys.partition_range_values where function_id=(select function_id from sys.partition_functions where name=@partFunctionName)) begin if exists(select * from sys.partition_range_values where function_id=(select function_id from sys.partition_schemes where name='Scheme_DateTime') and value=CONVERT(datetime,''+@limit+'',101)) begin print '界限已存在' end else begin exec('alter partition function '+@partFunctionName+'() split range('''+@limit+''')') print '修改分區函數,添加劃分界限為:'+@limit end end else begin print '分區函數不存在' end
這隻是本人的測試腳本,僅供參考~ 如有錯漏請大佬指導