SQL Server 大資料管理——資料歸檔(主檔案備份)
SQL Server 大資料管理——資料歸檔
背景:
資料庫幾百GB,甚至TB級別資料庫,歷史資料偶爾會用到,不能直接刪除,就需要定期歸檔歷史資料。以往在歸檔歷史資料方案:
方案1:做全備儲存歸檔資料,刪除線上庫歸檔資料
方案2:建立一個新庫,將歸檔資料匯入到新庫,備份保留新庫,刪除線上庫歸檔資料
對於方案1,這樣會有較多的不需要或者不能歸檔的資料重複備份,佔用大量空間,並且一旦歸檔資料需要使用,拷貝、還原需要時間較長,效率低;同時對還原需要空間也較難以匹配;方案2解決了資料重複備份佔用空間的問題,但資料轉移需要時間較長
因此,採用本文敘述的方案,表分割槽+資料庫主檔案備份的備份策略,可以同時很好的解決方案1、2的問題。
一. 主檔案資料移動到輔檔案
因為在進行檔案/組還原時,還需要用到主檔案,所以在每次資料歸檔時,同時要對主檔案備份歸檔,所以主檔案要儘可能的小。需要儘可能的將資料移動到輔助檔案上
1.1 新表處理:
修改資料庫預設檔案組,或者建立表時指定檔案組,使得新建立的表均在輔助檔案組上
--建立測試資料庫 CREATE DATABASE [test] CONTAINMENT = NONE ON PRIMARY ( NAME = N'test', FILENAME = N'D:\DB\test.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) LOG ON ( NAME = N'test_log', FILENAME = N'D:\DB\test_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB ) --增加檔案組和輔助檔案 alter database test add filegroup data alter database test add file (name=data,filename='D:\DB\data.ndf', SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP [data] alter database test add file (name=data1,filename='D:\DB\data1.ndf',size=8192KB,filegrowth=65536KB) to filegroup data
修改預設檔案組指令碼
USE [test]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'data')
ALTER DATABASE [test] MODIFY FILEGROUP [data] DEFAULT
GO
create table testdd(id int) select OBJECT_NAME(object_id) tableName,i.name indexName,s.name spaceName from sys.indexes i left join sys.data_spaces s on i.data_space_id=s.data_space_id where object_id =OBJECT_ID('dbo.testdd','U')
通過系統檢視發現,建立的testdd表是在預設的data檔案組下:
1.2 已經存在的表
1.2.1 不需要歸檔的表
不需要歸檔的表,可以通過建立、或刪除聚集索引將資料移動到輔助檔案上
alter database test add filegroup tableMetaData
alter database test add file
(name=tableMetaData,filename='D:\DB\tableMetaData.ndf', SIZE = 8192KB , FILEGROWTH = 65536KB ) TO FILEGROUP tableMetaData
alter database test add filegroup dataMD
alter database test add file(
name= dataMD,filename='D:\DB\dataMD.ndf',size=8192KB,filegrowth=65536KB
) to filegroup dataMD
create table testp(id int) on [primary]
create table testd(id int) on data
create table testMD(id int) on dataMD
create table testm(id int) on tableMetaData
--testp中插入100萬行資料
DECLARE @max AS INT, @rc AS INT;
SET @max = 1000000;
SET @rc = 1;
INSERT INTO testp VALUES(1);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.testp SELECT id + @rc FROM dbo.testp;
SET @rc = @rc * 2;
END
INSERT INTO dbo.testp
SELECT id + @rc FROM dbo.testp WHERE id + @rc <= @max;
go
--testm中插入100萬行資料
DECLARE @max AS INT, @rc AS INT;
SET @max = 100000;
SET @rc = 1;
INSERT INTO testm VALUES(1);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.testm SELECT id + @rc FROM dbo.testm;
SET @rc = @rc * 2;
END
INSERT INTO dbo.testm
SELECT id + @rc FROM dbo.testm WHERE id + @rc <= @max;
go
為testp表在檔案組data上建立聚集索引
建立索引之前檔案資料量
主檔案和輔檔案tableMetaData已經增長至9216,其他檔案任然初始大小
1.2.1.1 建立聚集索引移動資料
CREATE CLUSTERED INDEX [CIx_testp] ON [dbo].[testp]
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [data]
GO
從下圖可以看到此時testp的資料已經移到data檔案組下
通過下圖可以看到,data檔案大小增加一次,但主檔案大小並沒有減少
1.2.1.2 刪除聚集索引移動資料
CREATE CLUSTERED INDEX [CIx_testm] ON [dbo].[testm]
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = ON', ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [data]
GO
-- 刪除聚集索引,並指資料定儲存的檔案組
DROP INDEX [CIx_testm] ON dbo.testm WITH (MOVE TO [dataMD], ONLINE=ON)
GO
從下圖可以看到,testm表資料已經從tableMetaData檔案組移動到dataMD檔案組
同時從下圖可以看到,通過刪除聚集索引轉移資料,原檔案大小仍然沒有改變(tableMetaData仍然是9216KB)
1.3 需要定期歸檔表資料的轉移
根據歸檔規則,一般按資料產生的時間進行分割槽,建立表分割槽,一個分割槽對應一個檔案組的一個檔案
create table testpp(id int,date datetime) on [primary]
DECLARE @max AS INT, @rc AS INT;
SET @max = 1000000;
SET @rc = 1;
INSERT INTO testpp VALUES(1,'2018-01-01');
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.testpp SELECT id + @rc,DATEADD(MI,@rc,[date]) FROM dbo.testpp;
SET @rc = @rc * 2;
END
INSERT INTO dbo.testpp
SELECT id + @rc,DATEADD(MI,@rc,[date]) FROM dbo.testpp WHERE id + @rc <= @max;
go
此時主檔案大小仍然為9216KB沒有增長
系統檢視更新遲緩,導致檔案大小和真實資料大小不一致
下面對testpp表進行分割槽
--新增檔案組、檔案
use test
alter database test
add filegroup Before2019
alter database test
add filegroup After2019
alter database test
add file(name=N'Before2019',filename='D:\DB\testPartion\Before2019.ndf'
,size=1mb, filegrowth=1mb)
to filegroup Before2019
alter database test
add file(name=N'After2019',filename='D:\DB\testPartion\After2019.ndf'
,size=1mb, filegrowth=1mb)
to filegroup After2019
--建立分割槽函式
create partition function RangeTime(datetime)
as range left for values('2019-01-01')
--建立分割槽方案
create partition scheme RangeSchema_CreateTime
as partition [RangeTime]
to(Before2019,After2019)
GO
--為testpp表新增分割槽
USE [test]
GO
BEGIN TRANSACTION
CREATE CLUSTERED INDEX [ClusteredIndex_on_RangeSchema_CreateTime_636570819394124711] ON [dbo].[testpp]
(
[date]
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [RangeSchema_CreateTime]([date])
DROP INDEX [ClusteredIndex_on_RangeSchema_CreateTime_636570819394124711] ON [dbo].[testpp]
COMMIT TRANSACTION
1.4 收縮主檔案
不管是建立聚集索引轉移資料,刪除聚集索引轉移資料,或者建立表分割槽轉移資料,原始檔的空間都不會自動釋放,需要對原始檔進行收縮
USE [test]
GO
DBCC SHRINKFILE(N'test', 0) withno_infomsgs
--引數說明
--emptyfile 轉移資料到同文件組的其他檔案
--notruncate 移動資料頁到檔案前段,但不釋放空間
--truncateonly 不移動資料頁,釋放尾部空間
--with no_infomsgs 取消顯示所有資訊訊息
GO
二. 歸檔歷史資料
2.1 將歸檔分割槽資料轉為普通表資料
--在歸檔資料所在的分割槽檔案組上建立和歸檔表結構相同的表
create table testpp2018(id int,date datetime) on Before2019
--查詢partition_number 及其對應資料所在的檔案組
;with cte as
(select
object_id
,OBJECT_NAME(i.object_id) tableName
,i.index_id
,dds.partition_scheme_id
,dds.destination_id as partition_number
,fg.groupid
,fg.groupname
,f.fileid
,f.name
,f.filename
--,p.partition_id
--,p.rows
from sys.destination_data_spaces dds,sys.indexes i,sys.sysfilegroups fg,sys.sysfiles f
where dds.partition_scheme_id=i.data_space_id
and dds.data_space_id=fg.groupid
and fg.groupid=f.groupid
)
,cte1 as(
select
ps.data_space_id as partition_scheme_id
,ps.name partiton_schemes_name
,pf.name partition_function_name
,pf.function_id
--,prv.value AS BoundaryValue
from sys.partition_schemes ps ,sys.partition_functions pf--,sys.partition_range_values prv
where ps.function_id=pf.function_id
--and pf.function_id=prv.function_id
)
select cte.tableName,cte.groupname,cte.name,cte.filename
,cte.partition_number,cte1.partiton_schemes_name,cte1.partition_function_name,p.rows
,prv.boundary_id,prv.value BoundaryValue
from cte
inner join cte1 on cte.partition_scheme_id=cte1 .partition_scheme_id
left join sys.partition_range_values prv on cte1.function_id=prv.function_id and cte.partition_number=prv.boundary_id
left join sys.partitions p on cte.object_id=p.object_id and cte.index_id=p.index_id and cte.partition_number=p.partition_number
where cte.object_id=OBJECT_ID('dbo.testpp','U')
--要移出2019年以前的資料,即partition_number=1 的分割槽,從分割槽表中移除歸檔資料到普通表
alter table testpp switch partition 1 to testpp2018
從上圖可以看到分割槽1的記錄數已經為0,下面將把分割槽1合併掉,並移除對應的檔案和檔案組
use test
go
--合併分割槽1
alter partition function RangeTime()
merge range('2019-01-01 0:00:00')
--移除歸檔分割槽的檔案和檔案組
alter database test remove file [Before2019]
alter database test remove filegroup [Before2019]
通過建立聚集索引的方式將表資料從分割槽檔案移動到主檔案
CREATE CLUSTERED INDEX [ClusteredIndex-20180321-145814] ON [dbo].[testpp2018]
(
[id] ASC
) ON [PRIMARY]
GO
DROP INDEX [ClusteredIndex-20180321-145814] ON [dbo].[testpp2018] WITH ( ONLINE = OFF )
GO
2.2 備份主檔案
BACKUPDATABASE [test] FILEGROUP=N'PRIMARY'
TO DISK=N'E:\backup\test_PRIMARY_2018.bak'
WITHNOFORMAT,INIT, NAME =N'test-完整 資料庫 備份',SKIP,NOREWIND,NOUNLOAD, STATS= 10
GO
2.3 資料恢復測試
RESTOREDATABASE [test1] FILE=N'test'
FROM DISK=N'E:\backup\test_PRIMARY.bak'
WITH FILE= 1,
MOVEN'test'TON'D:\DB\test1\test1.mdf',
MOVEN'test_log'TON'D:\DB\test1\test1_1.ldf',
RECOVERY, replace, STATS= 10
GO
2.4 歸檔說明
備份的表格、時間區間列表
備份檔案路徑名稱
資料恢復指令碼,見2.3
2.5 刪除歸檔資料
truncatetable [dbo].[testpp2018]
droptable [dbo].[testpp2018]