SqlServer數據庫分區分表實例分享(有詳細代碼和解釋)


數據庫單表數據量太大可能會導致數據庫的查詢速度大大下降(感覺都是千萬級以上的數據表了),可以采取分區分表將大表分為小表解決(當然這只是其中一種方法),比如數據按月、按年分表,最后可以使用視圖將小表重新並為總的虛擬表,其實並不影響上層程序的使用(程序也許都不知道分表了)。

主要步驟:

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

這只是本人的測試腳本,僅供參考~ 如有錯漏請大佬指導

 


免責聲明!

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



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