1. 程式人生 > >SQL Server 大資料管理——資料歸檔(主檔案備份)

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]