SQL Server實(shí)現(xiàn)自動(dòng)循環(huán)歸檔分區(qū)數(shù)據(jù)腳本詳解
概述
大家應(yīng)該都知道在很多業(yè)務(wù)場(chǎng)景下我們需要對(duì)一些記錄量比較大的表進(jìn)行分區(qū),同時(shí)為了保證性能需要將一些舊的數(shù)據(jù)進(jìn)行歸檔。在分區(qū)表很多的情況下如果每一次歸檔都需要人工干預(yù)的話(huà)工程量是比較大的而且也容易發(fā)生紕漏。接下來(lái)分享一個(gè)自己編寫(xiě)的自動(dòng)歸檔分區(qū)數(shù)據(jù)的腳本,原理是分區(qū)表和歸檔表使用相同的分區(qū)方案,循環(huán)利用當(dāng)前的文件組,話(huà)不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
一、創(chuàng)建測(cè)試數(shù)據(jù)
----01創(chuàng)建文件組 USE [master] GO ALTER DATABASE [chenmh] ADD FILEGROUP [Group1] GO ALTER DATABASE [chenmh] ADD FILEGROUP [Group2] GO ALTER DATABASE [chenmh] ADD FILEGROUP [Group3] GO ALTER DATABASE [chenmh] ADD FILEGROUP [Group4] GO USE [master] GO ALTER DATABASE [chenmh] ADD FILE ( NAME = N'datafile1', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\datafile1.ndf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Group1] GO ALTER DATABASE [chenmh] ADD FILE ( NAME = N'datafile2', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\datafile2.ndf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Group2] GO ALTER DATABASE [chenmh] ADD FILE ( NAME = N'datafile3', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\datafile3.ndf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Group3] GO ALTER DATABASE [chenmh] ADD FILE ( NAME = N'datafile4', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\datafile4.ndf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP [Group4] GO ----02創(chuàng)建分區(qū)函數(shù) USE [chenmh] GO CREATE PARTITION FUNCTION [Pt_Range](BIGINT) AS RANGE RIGHT FOR VALUES (1000000, 2000000, 3000000) GO ----03創(chuàng)建分區(qū)方案,分區(qū)方案對(duì)應(yīng)的文件組數(shù)是分區(qū)函數(shù)指定的數(shù)量+1 CREATE PARTITION SCHEME Ps_Range AS PARTITION Pt_Range TO (Group1, Group2, Group3, Group4); ---04創(chuàng)建表,指定的分區(qū)列的數(shù)據(jù)類(lèi)型一定要和分區(qū)函數(shù)指定的列類(lèi)型一致。 CREATE TABLE [dbo].[News]( [id] [bigint] NOT NULL, [status] [int] NULL, CONSTRAINT [PK_News] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Ps_Range](id) ) ON [Ps_Range](id) -----創(chuàng)建歸檔分區(qū)表 CREATE TABLE [dbo].[NewsArchived]( [id] [bigint] NOT NULL, [status] [int] NULL, CONSTRAINT [PK_NewsArchived] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Ps_Range](id) ) ON [Ps_Range](id) ----插入測(cè)試數(shù)據(jù) DECLARE @id INT SET @id=1 WHILE @id<5001000 BEGIN INSERT INTO News VALUES(@id,@id%2) SET @id=@id+1 END
可以看到當(dāng)前總共有4個(gè)分區(qū),每一個(gè)分區(qū)定義的范圍區(qū)間是100萬(wàn),分區(qū)4我故意多插入了200多萬(wàn)的數(shù)據(jù)來(lái)驗(yàn)證自動(dòng)歸檔分區(qū)。
二、自動(dòng)歸檔分區(qū)腳本
CREATE PROCEDURE Pro_Partition_AutoArchiveData (@PartitionTable VARCHAR(300), @SwitchTable VARCHAR(300) ) AS BEGIN DECLARE @FunName VARCHAR(100),@SchemaName VARCHAR(100),@MaxPartitionValue sql_variant ---根據(jù)歸檔表查找對(duì)應(yīng)的分區(qū)方案、分區(qū)函數(shù)、最小分區(qū)數(shù)、最大分區(qū)范圍值 SELECT DISTINCT @FunName=MAX(pf.name), @SchemaName=MAX(ps.name), @MaxPartitionValue=max(isnull(prv.value,0)) FROM sys.partitions p inner join sys.indexes i ON p.object_id=i.object_id and p.index_id=i.index_id inner join sys.partition_schemes ps ON i.data_space_id=ps.data_space_id inner join sys.destination_data_spaces dds ON ps.data_space_id=dds.partition_scheme_id and dds.destination_id=p.partition_number inner join sys.data_spaces ds ON dds.data_space_id=ds.data_space_id inner join sys.partition_functions pf ON ps.function_id=pf.function_id LEFT join sys.partition_range_values prv ON pf.function_id=prv.function_id AND prv.boundary_id=p.partition_number-pf.boundary_value_on_right LEFT join sys.partition_parameters pp ON prv.function_id=pp.function_id and prv.parameter_id=pp.parameter_id LEFT join sys.types t ON pp.system_type_id=t.system_type_id and pp.user_type_id=t.user_type_id WHERE OBJECT_NAME(p.OBJECT_ID)=@PartitionTable DECLARE @MaxId BIGINT,@MinId BIGINT,@Sql NVARCHAR(MAX),@GroupName VARCHAR(100),@MinPartitionNumber INT SET @Sql= N'SELECT @MaxId=MAX(id),@MinId=Min(id) FROM '+@PartitionTable EXEC sp_executesql @Sql,N'@MaxId BIGINT out,@MinId BIGINT out',@MaxId OUT,@MinId OUT SELECT @FunName AS FunName,@SchemaName AS SchemaName,@MaxPartitionValue AS MaxPartitionValue ,@MaxId AS MaxId,@MinId AS MinId ---判斷當(dāng)前表的最大的id是否已經(jīng)在最大的分區(qū)中 IF @MaxId>=@MaxPartitionValue BEGIN ----歸檔分區(qū)數(shù)據(jù),根據(jù)表的最小值找到它所屬的分區(qū). SET @Sql= N'SELECT @MinPartitionNumber=$PARTITION.'+@FunName+N'('+CONVERT(VARCHAR(30),@MinId)+N')'; EXEC sp_executesql @Sql,N'@MinPartitionNumber INT out',@MinPartitionNumber OUT SET @Sql=N'ALTER TABLE ' +@PartitionTable+ N' SWITCH PARTITION '+CONVERT(VARCHAR(10),@MinPartitionNumber)+ N' TO ' +@SwitchTable+ N' PARTITION ' +CONVERT(VARCHAR(10),@MinPartitionNumber); --PRINT @Sql EXEC (@Sql) ---修改分區(qū)方案,增加新的分區(qū)對(duì)應(yīng)的文件組,根據(jù)最小的分區(qū)id找到對(duì)應(yīng)的文件組。 SELECT DISTINCT @GroupName=ds.name FROM sys.partitions p inner join sys.indexes i ON p.object_id=i.object_id and p.index_id=i.index_id inner join sys.partition_schemes ps ON i.data_space_id=ps.data_space_id inner join sys.destination_data_spaces dds ON ps.data_space_id=dds.partition_scheme_id and dds.destination_id=p.partition_number inner join sys.data_spaces ds ON dds.data_space_id=ds.data_space_id inner join sys.partition_functions pf ON ps.function_id=pf.function_id WHERE pf.name=@FunName AND ps.name=@SchemaName AND p.partition_number=@MinPartitionNumber SET @Sql=N'ALTER PARTITION SCHEME '+@SchemaName+N' NEXT USED '+@GroupName --PRINT @Sql EXEC (@Sql) ---修改分區(qū)函數(shù),增加新的分區(qū),增加新的分區(qū)范圍值,在現(xiàn)有的最大的值的基礎(chǔ)上加100萬(wàn)(需要和現(xiàn)有的分區(qū)函數(shù)的范圍保持一致) SET @MaxPartitionValue=CONVERT(BIGINT,@MaxPartitionValue)+1000000 SET @Sql=N'ALTER PARTITION FUNCTION '+@FunName+N'('+N')'+N' SPLIT RANGE ('+CONVERT(VARCHAR(30),@MaxPartitionValue)+N')' --PRINT @Sql EXEC (@Sql) END END
三、自動(dòng)歸檔分區(qū)數(shù)據(jù)
1.首次測(cè)試
EXEC Pro_Partition_AutoArchiveData 'news','NewsArchived';
注意:每調(diào)用一次歸檔一個(gè)最小分區(qū)的數(shù)據(jù)。
分區(qū)表的News分區(qū)1的數(shù)據(jù)被歸檔到了NewsArchived表中,且創(chuàng)建了分區(qū)5,分區(qū)5使用的是已歸檔的分區(qū)1的文件組,達(dá)到了循環(huán)利用文件組的效果。
2.再調(diào)用一次歸檔分區(qū)腳本
當(dāng)分區(qū)表最大的id小于最大的分區(qū)值時(shí)自動(dòng)歸檔分區(qū)腳本就不會(huì)生效。所以當(dāng)前的測(cè)試表數(shù)據(jù)還可以再歸檔分區(qū)3的數(shù)據(jù)。
3.經(jīng)過(guò)一段時(shí)間的運(yùn)行歸檔數(shù)據(jù)可能是這樣的效果
Group1→Group4→Group1→.......
四、腳本注意事項(xiàng)
1.@PartitionTable和@SwitchTable表必須使用同名的分區(qū)方案和分區(qū)函數(shù),否則@SwitchTable就需要單獨(dú)修改分區(qū)方案和函數(shù),且表結(jié)構(gòu)完全一致。
2.歸檔的表分區(qū)列數(shù)據(jù)類(lèi)型必須是INT類(lèi)型,且值是自增規(guī)律.
3.分區(qū)歸檔作業(yè)在備份作業(yè)后執(zhí)行
4.建議使用Right分區(qū),Left分區(qū)會(huì)出現(xiàn)有的最后一個(gè)分區(qū)文件組不會(huì)循環(huán)替換,一直處于分區(qū)的最后,比如Group1,Group2,Group3,Group1,Group2,Group3,Group1,Group4。期望的應(yīng)該是Group1,Group2,Group3,Group4,Group1,Group2,Group3,Group4,Group1
5.注意我當(dāng)前的每個(gè)分區(qū)大小是100萬(wàn)和分區(qū)函數(shù)保持一致,如果范圍值不同,需要修改最末尾代碼的"修改分區(qū)函數(shù)"處代碼.
總結(jié)
當(dāng)前自動(dòng)歸檔分區(qū)腳本如果要拷貝去用還是得能完全理解每一段代碼,根據(jù)自己的業(yè)務(wù)做適當(dāng)?shù)男薷?,畢竟?shù)據(jù)是無(wú)價(jià)的?。?!。最后只需要?jiǎng)?chuàng)建一個(gè)作業(yè)定期跑作業(yè)就行,重復(fù)執(zhí)行也不影響。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
一條語(yǔ)句簡(jiǎn)單解決“每個(gè)Y的最新X”的經(jīng)典sql語(yǔ)句
“每個(gè)Y的最新X”是一個(gè)經(jīng)典的SQL問(wèn)題,工作中經(jīng)常碰到。當(dāng)然不是“按Y分組求最新的X值”那么簡(jiǎn)單,要求最新X的那條記錄或主鍵ID。用一條SQL語(yǔ)句可以簡(jiǎn)單的解決此問(wèn)題。 生成實(shí)例表和數(shù)據(jù):2008-03-03sqlserver數(shù)據(jù)庫(kù)服務(wù)器讀寫(xiě)性能之陣列RAID對(duì)比簡(jiǎn)介
這篇文章主要考慮sqlserver數(shù)據(jù)庫(kù)服務(wù)器的讀寫(xiě)性能優(yōu)化之陣列raid的對(duì)比分析,需要的朋友可以參考下2024-04-04一條SQL語(yǔ)句修改多表多字段的信息的具體實(shí)現(xiàn)
修改兩張及以上表的時(shí)候,總得需要用幾次語(yǔ)句才修改,萬(wàn)一其中一條沒(méi)修改上,又沒(méi)事務(wù)機(jī)制的話(huà),處理很麻煩,下面為大家介紹下使用一條SQL語(yǔ)句修改多表多字段的信息2014-01-01order by newid() 各種數(shù)據(jù)庫(kù)隨機(jī)查詢(xún)的方法
order by newid() 各種數(shù)據(jù)庫(kù)隨機(jī)查詢(xún)的方法,需要的朋友可以參考一下2013-04-04如何強(qiáng)制刪除或恢復(fù)SQLServer正在使用的數(shù)據(jù)庫(kù)
如何強(qiáng)制刪除或恢復(fù)SQLServer正在使用的數(shù)據(jù)庫(kù)...2007-01-01Linux安裝ODBC連接SQLServer數(shù)據(jù)庫(kù)的步驟
這篇文章主要介紹了Linux安裝ODBC連接SQLServer數(shù)據(jù)庫(kù)?,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04用sql腳本創(chuàng)建sqlserver數(shù)據(jù)庫(kù)觸發(fā)器范例語(yǔ)句
創(chuàng)建SqlServer數(shù)據(jù)庫(kù)觸發(fā)器腳本范例,方便大家用sql來(lái)創(chuàng)建觸發(fā)器,學(xué)習(xí)sqlserver的朋友可以參考下。2010-09-09