接上文:SQL Server 列存储索引性能总结(3)——列存储的锁,列存储的其中一个强项在于非常高的压缩率,如果没有这个压缩功能,列存储不可能有极大的性能提升。本文就来演示一下压缩方面的内容。
案例测试
压缩率高不高直接看大小的变化已经足够了,这次我们使用ContosoRetailDW库的FactOnlineSales表,这个表有1200万数据,可以作为一个借鉴,我们先把数据挪到一个堆表:
select * into [FactOnlineSales_Heap]
from [dbo].[FactOnlineSales]
使用sp_spaceused命令检查当前大小:
常规聚集列存储索引
接下来创建聚集列存储索引:
create clustered columnstore index CCI on dbo.FactOnlineSales_Heap
再次检查大小: data从2020440 KB (1973MB)降到了172512 KB(168MB)
Archive聚集列存储索引
当然不会简单地到此结束,我们再来试一下另外一个参数:DATA_COMPRESSION = COLUMNSTORE_ARCHIVE
alter index all on dbo.FactOnlineSales_Heap rebuild with ( DATA_COMPRESSION = COLUMNSTORE_ARCHIVE );
然后获取大小,看看现在到底多大了?76400 KB(76MB)!
比常规的聚集列存储又少了一半以上。不过单纯的空间减少并不代表一切。为什么呢?因为这个选项从名字就可以看出是用来做“归档”的,针对那些很少用的数据,甚至可以理解为不用去怎么查询和操作的数据,几年用一次的那种,一旦频繁使用,那么解压过程可能会非常慢。
drop index cci on FactOnlineSales_Heap
GO
exec sp_spaceused '[FactOnlineSales_Heap]'
行压缩传统聚集索引
为了测试对比,我们这次来建一个传统的行存储聚集索引,并且使用行压缩功能:
create clustered index [CIX] on dbo.[FactOnlineSales_Heap] ( OnlineSalesKey asc ) with ( DATA_COMPRESSION = ROW );
空间为888392 KB(888MB),另外index_size也从个位数升到4位数。
页压缩传统聚集索引
接下来我们创建页压缩的聚集行存储索引:
create clustered index [CIX] on dbo.[FactOnlineSales_Heap] ( OnlineSalesKey asc ) with (DROP_EXISTING = ON, DATA_COMPRESSION = PAGE);
这一次的结果又不一样,350M,其实传统压缩中,页压缩已经足够了,因为页压缩自带有行压缩的功能。
在进行压缩钱,关于压缩的效果,可以使用这个存储过程来评估压缩效果,可以辅助你选择:
sp_estimate_data_compression_savings
[ @schema_name = ] 'schema_name'
, [ @object_name = ] 'object_name'
, [@index_id = ] index_id
, [@partition_number = ] partition_number
, [@data_compression = ] 'data_compression'
[;]
@schema_name: 表或索引的schema。
@object_name: 表或索引视图的名字。
@index_id: 可以指定某个索引,如果表上没有索引,可以使用0或NULL。
@partition_number: 分区号,如果没有索引,也要使用NULL。
@data_compression: 可以指定NONE(不压缩),ROW(行压缩),PAGE(页压缩),COLUMNSTORE(列存储)和在SQL 2019出现的COLUMNSTORE_ARCHIVE 进行压缩评估。
这个存储过程会提取一些样本,然后在TempDB上创建并计算。
小结
如果考虑一个数据库甚至数据表超过了TB级别,那么往往可以节省好几TB的空间。
聚集列存储索引使用RLE(Run-length Encoding,运行长度编码)技术来压缩,适合表中有很多重复数据的情况。对于Archive压缩,SQL Server使用了微软的XPRESS 压缩技术进一步压缩。
使用Archive压缩的索引,在查询时会比常规的聚集列存储索引更慢,同时CPU和内存使用率也更高。所以我再次说一下过往已经说过很多次的话,只要允许你选择用还是不用的选项,就要注意,因为它们都有适用场景和前提条件,不要只看到优点就忽视缺点。Archive更适合用于分区环境下,某些已经可以归档的分区上。
下面是一个结果对比,可以看出常规行存储已经足够好,不过要注意两个事情:
- 没有绝对完美的方案,需要看自己环境的需要。
- 无论哪种压缩,都是CPU密集型操作,同时解压也是需要考虑的。