SQL SERVER系列(三):SQL Server 2008中的数据压缩_sql2008压缩数据库
作者:我家小花儿 | 2024-08-09 16:50:20
赞
踩
sql2008压缩数据库
在本系列的
上一篇文章中,我列举了目前三大数据库(Oracle、DB2、SQL Server)在最新版本中使用的压缩技术的相关链接,关于SQL Server 2008的相关信息是最少的,因为直到目前为止,我们还不能拿到具有数据压缩功能的SQL Server 2008版本。一个好消息是,在SQL Server 2008的下一个社区预览版(CTP6)中,我们终于能够看到“数据压缩”功能的庐山真面目了(注:11月刚刚发布的SQL Server 2008社区预览版为CTP5)。这个好消息来源于SQL Server存储引擎开发组的博客
Data Compression will be available in CTP-6,在这篇博客(博客作者Sunil Agarwal为SQL Server Storage Engine组的一名程序经理)中同时提到,数据压缩功能将是企业版独有的。
在
Types of data compression in SQL Server 2008这篇博客中, Sunil Agarwal提到了在SQL Server 2008中采用的两种压缩策略:
(1)以变长格式存储所有的定长数据类型。在本系列的
上一篇文章中,我提到过在SQL Server 2005 SP2中提供的使用vardecimal类型来存储decimal/numeric数据类型以节省存储空间的问题,有兴趣的朋友可以参考上一篇文章最后列出的相关链接以获取更多信息。在SQL Server 2008中,微软将这一思想扩展到了所有的定长数据类型,例如integer,char,float类型。需要注意的是,虽然SQL Server 2008以变长格式存储所有的定长数据类型,但这只是一种存储的具体实现机制,并不会改变任何语义上的东西,任何客户的程序都不需要修改,因为它根本不关心也不必知道数据库内部具体的数据存储方式。
例子一:假设一个表中有一个32位整数列(integer),但是该列的值均在(0~255或-128~127)的范围内,那么SQL Server 2008就可以只用一个字节来存储该列的值,这与之前版本的SQL Server总是使用4个字节来存储该列相比,就节省了75%的空间。
例子二:假设一个表中有一个定长字符串列CHAR(100),在以前的SQL Server版本中,该列总是使用100个字节来存储(即使实际的字符串没有100个字节,也会在其后填充空格以达到长度正好为100)。但是在SQL Server 2008中,该列将根据实际字符串的长度来进行存储,例如"Hello"将只耗费5个字节存储空间,而"This is a longer string"将只需23个字节存储,分别带来95%和77%的存储空间的节省。
当然,在上述例子一中如果实际的数值变化范围超过了一个字节能够表示的范围,那么相应的压缩比就会降低;对于例子二也类似,如果实际的字符串长度接近100,那么压缩效果也会大大降低。这意味着压缩的效果将依赖于实际的数据值的分布,同时也依赖于表的架构定义,这可能不那么明显,但是想象一下上述的例子二,如果将列的定义改为CHAR(150),显然压缩的效果就更为显著。另外请注意,NULL值是不需要占用任何存储空间的(参见下面的行格式)。
在
SQL Server 2008 Data Compression这篇博客中,博客作者Shailan Chudasama用一副图形象的说明了上述例子一描述的场景:
图1 SQL Server 2008以变长格式存储整数类型列
在上面的图1中,我们注意到在SQL Server 2008中,存储一个字节能够表示的整数实际需要1.5个字节来存储,而不是我们上面例子一中所描述的一个字节,为什么会是这样呢?我们知道,在SQL Server中存储一个变长列时,需要额外的存储空间来存储该列在一个数据行中的位置,以便能够在需要的时候快速访问到该列,以下这幅图说明了在SQL Server 2000/2005中一个数据行是如何存储的:
图2 SQL Server 2000/2005中的数据行存储格式
从上面这副图2中,我们可以清楚的看到,一个定长列除了存储该列数据本身以外,是不需要额外的存储空间的。而对于一个变长列,除了该列数据本身所占的空间外,每个变长列还需要2个额外的字节来存储该列在数据行中的位置,这就是上图中的“Column Offset Array”。从这个意义上来将,将smallint甚至我们例子一中提到的integer数据类型以变长方式存储的压缩效果就几乎毫无意义了。因此在SQL Server 2008中针对这种情况进行了特殊的优化,那就是如果该列的长度不超过8字节,那么每列只需要4bit来存储上述的列偏移,这就清楚的解释了图1中的4Bits从何而来了。需要提醒大家的上,图2中的数据行存储格式在SQL Server 2008中依然有效,而且是默认的存储格式(我猜测应该是不启用数据压缩时所使用存储格式)。
在SQL Server 2008中,这种压缩策略是通过在DDL(数据操纵语言)中的“ROW COMPRESSION"而暴露出来的,这也就是我们通常所说的行级压缩(Row level compression)。
(2) 与上面所说的行级压缩相对应,在SQL Server 2008中所采用的另外一种压缩策略是”页级压缩(Page level compression)",它是在一个数据页内部减少一个或多个数据行的列之间的数据冗余。它的设计思想是:在一个数据页(对于SQL Server为8KB)内部,对于冗余数据只存储一次,然后在用到的地方进行多次引用而非多次重复存储,以此来减少存储空间的占用。例如如下的表:
Table employee( name varchar(100), status varchar (10) default ‘full time’)
对于这样一个表,如果插入很多数据行,那么很可能很多行的status列都是使用默认的"full time“值。这种情况下,SQL Server 2008可以通过在数据页内只存储"full time"一次,然后在其他需要的地方进行引用,这样存储空间自然减少了。很显然,这种压缩策略的效果取决于冗余数据的数量。
在
SQL Server 2008 Data Compression这篇博客中,博客作者Shailan Chudasama用以下两幅图说明了页级压缩的实现原理,与行级压缩一样,页级压缩也是通过DDL暴露给用户的。
图3 通过引用减少冗余数据的存储