原文出处:http://www.sqlnotes.cn/post/2013/09/05/DBA-Daily-Jobs-One%E2%80%94%E2%80%94-Archiving-Data
问题:
随着数据库越来越大,对性能及管理方面的挑战也会越来越大。每次查询可能需要查找更多的数据页,特别是当查询存在扫描操作时,会导致查询越来越慢。同时,需要备份的数据也会越来越多,备份操作持续越来越久。备份文件及数据库所使用的数据文件也会越来越大等等,一系列的问题都会随之产生。
此时数据归档就变成非常重要。数据归档和容量规划其实息息相关,不过容量规划将在别的文章中介绍。
数据归档的目标是监控数据的大小和增长速度,这里特别重要的是即使是小库,也要做好规划,因为你几乎无法保证小库以后会不会在未来的某个时间段快速增长或者变得非常重要,做好规划将会对未来的管理和优化都有非常重要的影响。另外,归档意味着数据需要保存,以便后续使用,也就是说,你不能直接删除。因为很多数据仓库需要这些数据,但是业务数据库并不总是需要保存,这时候又体现出归档的重要性。
另外,归档的好处正如开始所说的,减少备份文件的大小,加快数据库还原的速度和资源开销,减少管理数据库的开销,提高运行性能等等,整理数据时,也只需要整理活动数据即可。
总之,做好数据归档、容量规划是作为DBA或者管理数据库人员日常工作的重点任务之一。
思考:
1、定位哪些数据需要保留?
一般归档的数据都是有比较明显的时间列或者业务列,这一点能比较好地标识出需要处理的数据。但是具体还是需要根据业务需求而定。
2、如何在需要的时候能够访问这些数据?
根据归档的方式,访问数据有不同的方式,这个在下面会分别描述。
3、归档数据的安全性要求?
由于归档数据不再存在于对应的表甚至库甚至服务器上,所以在归档的时候要考虑好安全性问题,同时对归档数据的保存也要做好考虑。
解决方案:
对于上面的问题,有这几个需要考虑的地方:
-
如果数据必须保存在同一个数据库:
那么可以把需要归档的数据移到新的表,从实践上来说,归档表应该有一定的前缀或者后缀,以便日常使用。同时,把这些表放到一个独立的文件组中,因为这些文件几乎就只有“只读”的特性,所以放到一个文件组中,一方面,可以减少备份大小,你只需要使用文件备份或者部分备份功能,备份活动的数据所在的文件组即可。至于归档数据,只需要定期做一次备份即可。还原的时候也快。另外一方面,由于这部分的文件组是只读的,所以可以使用一些对于静态数据很有效的性能提高技术,如索引视图、列存储索引等,另外对于只读文件及文件组,不需要加锁,可以减少锁争用的问题。
但是需要注意如果你做一次完整备份,这部分数据还是会包含在备份文件里面,并没有减少文件大小,所以对于这类归档,通常建议使用部分备份或者文件备份。另外就是当需要访问这些数据的时候,一般都是使用视图,合并所需的数据然后展示,这种展示一般性能不会有很大的提升,因为视图不是用来提升性能的,同时在权限访问方面也要考虑,但是由于都在一个库,所以这方面的影响并不是非常明显。
对于这种情况的归档,2005及以后版本出现了一个非常有用的功能——表分区,通过表分区,可以在逻辑上不做任何改变,但是物理上已经分成了若干个区,理想情况下,数据操作可以仅仅发生在少数几个甚至一个区里面,配以分区索引,能够很好地提升I/O利用率。如果加上合适的数据压缩功能(记住不是收缩,2008才出现的功能),更能提升I/O利用率和降低空间使用率。
下面是示例操作,演示如何把不需要的数据移到新的文件组并做访问操作,本例子包含两种实现方式:
- 对于2000或者2005以上,但是不支持表分区的版本,如标准版,只能用这种方式。
- 是演示如何使用表分区来实现。
下面先演示不用表分区来实现:
1、创建文件组,并创建文件单独用来存放归档数据,本例使用示例数据库AdventureWorks2012中的表Sales.SalesOrderHeader,归档该表2006年的数据:
1: USE master
2:
3: GO
4:
5: ALTER DATABASE AdventureWorks2012
6:
7: ADD FILEGROUP Test1FG1;
8:
9: GO
10:
11: ALTER DATABASE AdventureWorks2012
12:
13: ADD FILE
14:
15: (
16:
17: NAME = test1dat3,
18:
19: FILENAME = 'D:\DB_Data\t1dat3.ndf',
20:
21: SIZE = 5MB,
22:
23: MAXSIZE = 100MB,
24:
25: FILEGROWTH = 5MB
26:
27: ),
28:
29: (
30:
31: NAME = test1dat4,
32:
33: FILENAME = 'D:\DB_Data\t1dat4.ndf',
34:
35: SIZE = 5MB,
36:
37: MAXSIZE = 100MB,
38:
39: FILEGROWTH = 5MB
40:
41: )
42:
43: TO FILEGROUP Test1FG1;
44:
45: GO
查看文件组及文件信息:
1: SELECT * FROM sys.filegroups
结果如下:
查看文件信息:
1: USE AdventureWorks2012
2:
3: GO
4:
5: SELECT file_guid,name,physical_name
6:
7: FROM sys.database_files
结果如下:
可以看到已经创建了两个文件了。
2、现在把需要归档的数据,在新文件组的文件中创建归档表,并插入:
1: USE AdventureWorks2012
2:
3: GO
4:
5: /*
6:
7: 由于需要指定表所在的文件,所以不能用select * into 来创建表
8:
9: */
10:
11: IF OBJECT_ID(N'Sales.Ar_SalesOrderHeader','U') IS NULL
12:
13: CREATE TABLE Sales.Ar_SalesOrderHeader
14:
15: (
16:
17: [SalesOrderID] [INT] IDENTITY(1, 1) NOT FOR REPLICATION NOT NULL,
18:
19: [RevisionNumber] [TINYINT] NOT NULL CONSTRAINT [DF_Arc_SalesOrderHeader_RevisionNumber] DEFAULT ((0)),
20:
21: [OrderDate] [DATETIME] NOT NULL CONSTRAINT [DF_Arc_SalesOrderHeader_OrderDate] DEFAULT (Getdate()),
22:
23: [DueDate] [DATETIME] NOT NULL,
24:
25: [ShipDate] [DATETIME] NULL,
26:
27: [Status] [TINYINT] NOT NULL CONSTRAINT [DF_Arc_SalesOrderHeader_Status] DEFAULT ((1)),
28:
29: [OnlineOrderFlag] [dbo].[FLAG] NOT NULL CONSTRAINT [DF_Arc_SalesOrderHeader_OnlineOrderFlag] DEFAULT ((1)),
30:
31: [SalesOrderNumber] AS ( Isnull(N'SO'
32:
33: + CONVERT([NVARCHAR](23), [SalesOrderID]), N'*** ERROR ***') ),
34:
35: [PurchaseOrderNumber] [dbo].[ORDERNUMBER] NULL,
36:
37: [AccountNumber] [dbo].[ACCOUNTNUMBER] NULL,
38:
39: [CustomerID] [INT] NOT NULL,
40:
41: [SalesPersonID] [INT] NULL,
42:
43: [TerritoryID] [INT] NULL,
44:
45: [BillToAddressID] [INT] NOT NULL,
46:
47: [ShipToAddressID] [INT] NOT NULL,
48:
49: [ShipMethodID] [INT] NOT NULL,
50:
51: [CreditCardID] [INT] NULL,
52:
53: [CreditCardApprovalCode] [VARCHAR](15) NULL,
54:
55: [CurrencyRateID] [INT] NULL,
56:
57: [SubTotal] [MONEY] NOT NULL CONSTRAINT [DF_Arc_SalesOrderHeader_SubTotal] DEFAULT ((0.00)),
58: