五分钟聊T-SQL:数据压缩
在Microsoft SQL Server 2008 开始就提供了数据压缩,数据压缩分为两类:
一是数据库备份压缩,二是数据对象压缩(表/索引)。
传说中数据压缩能压缩到原始数据的1/10,但是... ... 但是至少目前为止我还没遇到过这样的情形,通常情况下能压缩到原始数据的1/5-2/5的样子。
一、做数据压缩有哪些好处呢?
1. 数据压缩以后可以释放出大量的存储空间(-- 对公司来说是件好事,可以减少在存储容量上边的花费了);
2. 数据库查询IO更快(-- 磁盘磁头可以寻找更小的区域找到所需要的数据,比起做半天性能调优最终还是要去找那么多数据的DBA来说是件好事)。
二、如何有效地规避数据压缩的一些不利因素?
当然数据压缩不是绝对的好,它自身也有一些限制,我们可以采用如下方式规避这些不利因素:
1、 实施数据压缩后的数据对象在访问的时候需要解压缩,这将导致CPU使用率提高,但是随着硬件的发展CPU资源早就不是我们DBA考虑的主要因素之一了,一般来说进行过基础优化的数据库,CPU使用率不会超过25%... ... 话说我维护的数据库大部分时间CPU使用率保持在5%以下,这个跟业务性质有比较大的关系,一般造成CPU使用率虚高的情况都是由于索引使用不合理导致的。
2、如果进行数据库还原操作,还原过程中需要提供原始数据库没有压缩时候相同或更大一些的存储,否则还原会失败,当然我们可以采用文件组备份还原来尽量避免全库一次性还原。
三、如何对数据进行压缩?
压缩分为两种模式,Row行级压缩/Page页级压缩,一般情况下Page压缩比Row压缩会压缩得更多[×Row/Page压缩相关的具体原理还是参考一下MSDN吧,这里就大致上给出几个常用的SQL]
01.-- 忘了提一下:数据压缩只有企业版/数据中心版提供
02.-- 评估压缩后数据量相关信息
03.表
04.EXECsp_estimate_data_compression_savings 'Schema', 'TableName', NULL, NULL,'PAGE/ROW' ;
05.索引
06.EXECsp_estimate_data_compression_savings 'Schema', TableName', 3, NULL, 'PAGE/ROW';
07.-- 这里的 3 是需要你从sys.indexes 里边获取该表对应索引的ID来替换的!!
01.-- 压缩已存在的非分区表
02.ALTER TABLE TableName
03.REBUILD WITH (DATA_COMPRESSION =NONE/ROW/PAGE);
04.GO
05.
06.-- 压缩已存在的非分区索引
07.-- 一般我喜欢加入索引重建时在TempDB进行排序,同时使用联机重建,这样不会影响当前业务
08.ALTER INDEX IX_IndexName ONSchema.TableName
09.REBUILD WITH (DATA_COMPRESSION =NONE/ROW/PAGE,SORT_IN_TEMPDB = ON,ONLINE = ON);
10.GO
11.
12.-- 压缩已存在的分区表
13.ALTER TABLE PartitionTable1
14.REBUILD PARTITION = 1/ALL WITH(DATA_COMPRESSION = NONE/ROW/PAGE);
15.GO
16.-- 这里的 1 代表的是sys.partitions的 PartitionNumber
17.-- 分区表中每一个分区的压缩类型可以是不一样的
18.-- ALL 代表的是全部压缩,但是如果是已经有相当多的数据的分区表,个人不建议直接ALL压缩,这将会将ldf文件撑到非常大(有多少数据多少数据都会放置到ldf),如果需要全表或全分区索引压缩,建议最好写个While循环分区,对每个分区进行压缩,同时每个分区压缩完成后如果想尽快释放老日志,建议加入CHECKPOINT(这个方式仅对大容量日志模式/简单还原模式有效,由于完整还原模式是累计所有日志,故只能采用硬扛的方式加大存储来解决)
19.-- 注:一个压缩是一个事务,如果一个大压缩在执行过程中出现异常回滚或手工停止后回滚,回滚过程非常耗时,完全依赖于ldf的回滚方式... ...
20.
21.-- 压缩已存在的分区索引
22.ALTER INDEX IX_IndexName ONSchema.TableName
23.REBUILD PARTITION = 1/ALL WITH(DATA_COMPRESSION = NONE/ROW/PAGE,SORT_IN_TEMPDB = ON,ONLINE = ON) ;
24.GO