SQL Server实现自动循环归档分区数据脚本详解
发布时间 - 2026-01-11 03:25:03 点击率:次概述

大家应该都知道在很多业务场景下我们需要对一些记录量比较大的表进行分区,同时为了保证性能需要将一些旧的数据进行归档。在分区表很多的情况下如果每一次归档都需要人工干预的话工程量是比较大的而且也容易发生纰漏。接下来分享一个自己编写的自动归档分区数据的脚本,原理是分区表和归档表使用相同的分区方案,循环利用当前的文件组,话不多说了,来一起看看详细的介绍吧。
一、创建测试数据
----01创建文件组 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创建分区函数 USE [chenmh] GO CREATE PARTITION FUNCTION [Pt_Range](BIGINT) AS RANGE RIGHT FOR VALUES (1000000, 2000000, 3000000) GO ----03创建分区方案,分区方案对应的文件组数是分区函数指定的数量+1 CREATE PARTITION SCHEME Ps_Range AS PARTITION Pt_Range TO (Group1, Group2, Group3, Group4); ---04创建表,指定的分区列的数据类型一定要和分区函数指定的列类型一致。 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) -----创建归档分区表 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) ----插入测试数据 DECLARE @id INT SET @id=1 WHILE @id<5001000 BEGIN INSERT INTO News VALUES(@id,@id%2) SET @id=@id+1 END
可以看到当前总共有4个分区,每一个分区定义的范围区间是100万,分区4我故意多插入了200多万的数据来验证自动归档分区。
二、自动归档分区脚本
CREATE PROCEDURE Pro_Partition_AutoArchiveData
(@PartitionTable VARCHAR(300),
@SwitchTable VARCHAR(300)
)
AS
BEGIN
DECLARE @FunName VARCHAR(100),@SchemaName VARCHAR(100),@MaxPartitionValue sql_variant
---根据归档表查找对应的分区方案、分区函数、最小分区数、最大分区范围值
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
---判断当前表的最大的id是否已经在最大的分区中
IF @MaxId>=@MaxPartitionValue
BEGIN
----归档分区数据,根据表的最小值找到它所属的分区.
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)
---修改分区方案,增加新的分区对应的文件组,根据最小的分区id找到对应的文件组。
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)
---修改分区函数,增加新的分区,增加新的分区范围值,在现有的最大的值的基础上加100万(需要和现有的分区函数的范围保持一致)
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
三、自动归档分区数据
1.首次测试
EXEC Pro_Partition_AutoArchiveData 'news','NewsArchived';
注意:每调用一次归档一个最小分区的数据。
分区表的News分区1的数据被归档到了NewsArchived表中,且创建了分区5,分区5使用的是已归档的分区1的文件组,达到了循环利用文件组的效果。
2.再调用一次归档分区脚本
当分区表最大的id小于最大的分区值时自动归档分区脚本就不会生效。所以当前的测试表数据还可以再归档分区3的数据。
3.经过一段时间的运行归档数据可能是这样的效果
Group1→Group4→Group1→.......
四、脚本注意事项
1.@PartitionTable和@SwitchTable表必须使用同名的分区方案和分区函数,否则@SwitchTable就需要单独修改分区方案和函数,且表结构完全一致。
2.归档的表分区列数据类型必须是INT类型,且值是自增规律.
3.分区归档作业在备份作业后执行
4.建议使用Right分区,Left分区会出现有的最后一个分区文件组不会循环替换,一直处于分区的最后,比如Group1,Group2,Group3,Group1,Group2,Group3,Group1,Group4。期望的应该是Group1,Group2,Group3,Group4,Group1,Group2,Group3,Group4,Group1
5.注意我当前的每个分区大小是100万和分区函数保持一致,如果范围值不同,需要修改最末尾代码的"修改分区函数"处代码.
总结
当前自动归档分区脚本如果要拷贝去用还是得能完全理解每一段代码,根据自己的业务做适当的修改,毕竟数据是无价的!!!。最后只需要创建一个作业定期跑作业就行,重复执行也不影响。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
# sqlserver
# 分区
# sql
# server自动归档
# server
# 归档
# SQL server 2005的表分区
# SQLSERVER 表分区操作和设计方法
# SQLServer 通用的分区增加和删除的算法
# SQL Server根据分区表名查找所在的文件及文件组实现脚本
# 分区表
# 自己的
# 的是
# 测试数据
# 循环利用
# 也不
# 好了
# 还可以
# 首次
# 是这样
# 说了
# 不多
# 有一定
# 就行
# 达到了
# 可以看到
# 只需要
# 这篇文章
# 无价
# 比较大
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
三星网站视频制作教程下载,三星w23网页如何全屏?
常州企业网站制作公司,全国继续教育网怎么登录?
无锡营销型网站制作公司,无锡网选车牌流程?
高端智能建站公司优选:品牌定制与SEO优化一站式服务
如何构建满足综合性能需求的优质建站方案?
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
Laravel如何处理CORS跨域请求?(配置示例)
Firefox Developer Edition开发者版本入口
智能起名网站制作软件有哪些,制作logo的软件?
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
js实现点击每个li节点,都弹出其文本值及修改
如何注册花生壳免费域名并搭建个人网站?
电商网站制作价格怎么算,网上拍卖流程以及规则?
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
Laravel如何实现本地化和多语言支持?(i18n教程)
如何快速搭建高效WAP手机网站?
百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧
Laravel如何生成API文档?(Swagger/OpenAPI教程)
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】
laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置
🚀拖拽式CMS建站能否实现高效与个性化并存?
php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】
JavaScript数据类型有哪些_如何准确判断一个变量的类型
如何用腾讯建站主机快速创建免费网站?
微信推文制作网站有哪些,怎么做微信推文,急?
佛山企业网站制作公司有哪些,沟通100网上服务官网?
大型企业网站制作流程,做网站需要注册公司吗?
如何用已有域名快速搭建网站?
手机网站制作与建设方案,手机网站如何建设?
Laravel怎么实现模型属性的自动加密
HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】
使用C语言编写圣诞表白程序
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
简历在线制作网站免费版,如何创建个人简历?
如何彻底卸载建站之星软件?
制作电商网页,电商供应链怎么做?
潮流网站制作头像软件下载,适合母子的网名有哪些?
Laravel如何实现事件和监听器?(Event & Listener实战)
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
如何在腾讯云免费申请建站?

