深度压缩的存储节省和性能影响与数据、数据库本身的设计、数据库调优程度以及应用程序负载有关。我将解释这项新技术的工作方式,并展示如何启用表压缩。 来自 IBM Database Magazine 。
组织现在生成的数据比任何时候都要多。为了遵从法律法规,组织必须将数据保留更长的时间。结果:数据库以不可思议的速度增长。根据行业分析师的说法,企业数据库以每年125%的速度增长。 数据的暴增给企业的存储、保护、发布以及从海量数据中获取价值带来了极大的压力。IBM 在 DB2 9 for Linux、Unix 和 Windows 中引入了一项名为深度压缩(deep compression)的技术,以应对该挑战。
尽 管深度压缩的主要目的是节省存储空间,但是使用它也可以大大节省磁盘 I/O 并提交缓冲池命中率。因而可以提高性能,并无需成本——数据压缩和解压缩需要占用额外的 CPU 周期。深度压缩的存储节省和性能影响与数据、数据库本身的设计、数据库调优程度以及应用程序负载有关。我将解释这项新技术的工作方式,并展示如何启用表压 缩。
随 着数据的增长,相对基数呈下降趋势。世界上并没有那么多真正“独特”的事物。事物的整体可能是独特的,但是基本元素不一定是不同的。试想一下元素周期表 ——世界上所有的事物都由很小的元素集合组成。数据也是如此。例如,美国最近的人口普查表明,在美国居住着 3 亿人口。但是只有 78800 种不同的姓氏,致使某些姓名集合中出现大量名字聚集,因而出现非常低的基数。
![]() ![]() |
![]()
|
深 度压缩在数据中搜索重复的模式,使用 12 位符号替换这些模式,这些符号及其表示的模式一起存储在静态目录中(请参见图 1)。创建该目录后,它将与压缩数据一起存储在表中,为解压缩而访问该表中的数据时,它将加载到内存中。DB2 9 将在整个表中搜索一个行的多个列中重复的列值和模式。DB2 还将搜索作为给定列的子字符串的重复模式。只在有可能节省存储空间的情况下才压缩数据。整个行将存储为 12 位符号的集合,不会对行进行部分压缩。
图 1. 深度压缩工作原理![深度压缩工作原理](https://i-blog.csdnimg.cn/blog_migrate/3d69c65ca64ba172f6ad1853ce064cbe.png)
要对表进行深度压缩,必须满足以下两个先决条件:
- 必须在表级别启用压缩。
- 必须存在表的压缩字典。
![]() ![]() |
![]()
|
要 在表级别启用压缩,可以执行 CREATE TABLE SQL 语句或者 ALTER TABLE 语句,同时指定 COMPRESS YES 选项。例如,如果想创建一个名为 EMPLOYEE 的新表并对其启用深度压缩,可以执行如下 CREATE TABLE 语句:
清单 1. 创建一个新表并启用深度压缩 CREATE TABLE employee (name VARCHAR(60), dept CHAR(3), salary DECIMAL(7,2), city VARCHAR(25), state CHAR(2), zipcode VARCHAR(10)) COMPRESS YES |
要对现有的 EMPLOYEE 表启用深度压缩,可以执行以下 ALTER TABLE 语句:
清单 2. 对现有表启用深度压缩 ALTER TABLE employee COMPRESS YES |
![]() ![]() |
![]()
|
尽 管可以通过将 COMPRESS 属性设置为 YES 随时对表启用深度压缩,但是在压缩字典建好之前不会发生压缩。构建压缩字典(和压缩表中的现有数据)需要执行离线(经典)表重组,该操作可以通过在指定 KEEPDICTIONARY 或 RESETDICTIONARY 选项的情况下执行 REORG 实现。如果在指定这两个选项的情况下执行了 REORG 命令,并且不存在压缩字典,则将构建一个新字典。如果在指定这两个选项的情况下执行了 REORG 命令,但已经存在压缩字典,则现有字典将被重新创建 (RESETDICTIONARY) 或保留不变 (KEEPDICTIONARY),并且数据将被重组或压缩。
要为启用了深度压缩的 EMPLOYEE 表创建一个新的压缩字典,请执行以下命令:
清单 3. 为深度压缩表创建一个压缩字典 REORG TABLE employee RESETDICTIONARY |
执行此命令时,将分析存储在 EMPLOYEE 表中的数据,构造压缩字典并存储在表的开始部分,所有现有数据将压缩并直接写入到该表压缩字典的后面。图 2 展示了在应用深度压缩前 EMPLOYEE 表的样子。
图 2. 构建压缩字典和应用深度压缩时表数据的变化![构建压缩字典和应用深度压缩时表数据的变化](https://i-blog.csdnimg.cn/blog_migrate/089ef9c44b3ee0c691ab7a684c2083c5.png)
注意,深度压缩不会影响索引数据,只压缩存储在基本表(base table)页面上的数据。但是,由于压缩表中的记录以压缩形式在存储器和内存之间移动。
所以压缩表中写入事务日志文件的记录也将压缩。(为了压缩和解压缩而访问表时将在内存中加载压缩字典。)
![]() ![]() |
![]()
|
由 于构建压缩字典和执行数据压缩时需要离线重组,压缩数据所需的初始开销可能很高。因此,如果能知道哪些表最能从深度压缩中获益哪些表不行,则会很有帮助。 Inspect 工具可以解决这个问题。在指定 ROWCOMPESTIMATE 选项的情况下执行 INSPECT 命令可以调用 Inspect 工具,它将检查指定表中的每一行,通过找到的数据构建一个压缩字典,然后使用该字典估计压缩将节省的空间。
要估计压缩名为 EMPLOYEE 的表时能节省多少存储空间,可以执行以下 INSPECT 命令:
清单 4. 查看压缩节省的空间大小 INSPECT ROWCOMPESTIMATE TABLE NAME employee 返回的信息如下: DATABASE: TEST VERSION: SQL09000 2007-06-06-12.35.58.14.296000 Action: ROWCOMPESTIMATE TABLE Schema name: PAYROLL Table name: EMPLOYEE Tablespace ID: 4 Object ID: 6 Result file name: emp Table phase start (ID Signed: 6, Unsigned: 6; Tablespace ID:4) PAYROLL.EMPLOYEE Data phase start. Object: 6 Tablespace : 4 Row compression estimate results: Percentage of pages saved from compression: 46 Percentage of bytes saved from compression: 46 Percentage of rows ineligible for compression due to smallrow size: 0 Compression dictionary size: 13312 bytes. Expansion dictionary size: 10240 bytes. Data phase end. Table phase end. |
如果在执行 INSPECT 命令之前对表启用了深度压缩,则构建并用于评估空间节省的压缩字典将写入表,位于现有的数据的结束处(假设不存在压缩字典,否则创建的压缩字典将被销 毁)。图 3 展示了一个启用压缩的表在使用 Inspect 估计节省的存储量之前和之后的情形。
图 3. 使用 Inspect 工具评估启用深度压缩的表时表数据的变化![使用 Inspect 工具评估启用深度压缩的表时表数据的变化](https://i-blog.csdnimg.cn/blog_migrate/16365668ea3e5706bf68e8974f1982d1.png)
构造了压缩字典并写入表后,添加到该表的新记录将自动压缩。如果压缩字典由 Inspect 工具创建,则在执行离线表重组前,表中之前存在的记录保持不变,或者被更新(这种情况下,每个修改的记录都将压缩)。
![]() ![]() |
![]()
|
使 用深度压缩减少了保存表数据所需的存储空间后,您可能还希望调整表占据的空间大小,将回收的存储空间用在其他地方。如果使用的是 SMS 表空间,回收的存储空间将自动返回给系统文件,这是表重组过程的一部分。但是,如果使用的是 DMS 表空间,则情况有所不同。DMS 表空间(以及基于 DMS 表空间的自动存储表空间)可以通过执行相应形式的 ALTER TABLESPACE SQL 语句调整大小。例如,要将为 TBSP1 表空间使用的每个容器所分配的存储空间量减少 200MB,可以执行以下 ALTER TABLESPACE 语句:
清单 5. 调整容器所分配的存储空间量 ALTER TABLESPACE tbsp1 REDUCE (ALL CONTAINERS 200 M) |
(除了重新调整所有容器大小,还可以通过 丢弃一个或多个存储容器回收空间)。但是,实际返回给文件系统以供重新分配的存储空间量取决于要调整大小的表空间的高水位标记(high-water mark)。(高水位标记表示表空间中分配最多空间的页面;高水位标记是 DMS 独有的概念。)
![]() ![]() |
![]()
|
在 表中存储一行数据时,DB2 将给该行分配一个惟一的记录标识符,称为 RID。在 DB2 9 之前,RID 包括一个三字节的页面编号和一个单字节的页槽号(slot number)。页槽号是页槽目录中的一个数组条目,它包含行数据在数据页面中的偏移量,表示行数据的物理位置;页面编号表示数据页面本身。DB2 9 能够支持 4 字节 RID 和更大的 6 字节 RID,后者由一个 4 字节页面编号和一个双字节页槽号组成(DMS LARGE 表空间中的表使用这两种 RID)。因此,您可以拥有一个包含 255 行以上的数据页面(4 字节 RID 的限制),使用 4k 的页面时单个表分区的大小可以达到 2TB(使用 32K 页面时可以达到 16TB)在 DB2 9 中,对于新建的自动存储表空间和 DMS 表空间,默认使用 6 字节 RID。
DB2 索引使用与表空间相对的 RID 引用基本表记录。(索引是一个引用基本表中的行的有序指针集。)这意味着,DB2 索引中的每个键都指向表空间页面 Y 中的页槽 X,不是基本表页面 Y 的页槽 X。因此,DB2 无法自由地围绕表空间扩展;如果它这样做了,索引中存储的 RID 将指向错误的数据,并且每次发生移动时都需要重新构建引用表空间数据的每个索引。
使用与表空间相对的 RID 可以扫描表的范围地图页面,减少了指出特定页面在表空间中位置的步骤,从而提高了性能。因为 DB2 不能改变表空间中范围的放置,因此只释放高水位标记后面不使用的存储空间。
执行离线表数重组的方式(要求压缩表数据)可能会影响表空间的高水位标记。如果使用临时表空间重组和压缩表数据,得到的表版本是在临时表空间中构造的,在原表页面的原表对象上复制它的数据页面,并截取要使用的存储空间。
图 4 展示了一个包含 4 个表(TABLE_1、TABLE_2、TABLE_3 和 TABLE_4)的表空间在使用临时表空间重组和压缩前后的变化。压缩了全部的 4 个表后,将释放更多的空间。但是,这些空间分散在整个表空间中。高水位标记没有明显的降低。
图 4. 使用临时表空间进行的表重组/压缩操作如何影响表空间的高水位标记![使用临时表空间进行的表重组/压缩操作如何影响表空间的高水位标记](https://i-blog.csdnimg.cn/blog_migrate/65a4a03fe784e92c7c0ad1acb5e741b4.png)
如 果没有使用临时表空间重组和压缩表数据,则新的表将在原表的表空间中创建,并最终删除原表。因此,表重组和压缩的顺序以及这些表的位置(不幸的是,没有确 定位置的简单方法)都会大大影响表在表空间中的布局,以及表空间高水位标记的放置方式。图 5 展示了包含 4 个表(TABLE_1、TABLE_2、TABLE_3 和 TABLE_4)的原表空间在按以下顺序重组和压缩(未使用临时表空间)时所有 4 个表的前后变化:TABLE_1、TABLE_2、TABLE_3、TABLE_4。
图 5. 不使用临时表空间的表重组/压缩操作如何影响表空间的高水位标记![不使用临时表空间的表重组/压缩操作如何影响表空间的高水位标记](https://i-blog.csdnimg.cn/blog_migrate/4686c10e9ee0cc9147cf5ffe9e580c7f.png)
在这种情况下,我们得到的高水位标记将比开始重组和压缩操作之时要高。但是,如果我们再次重组和压缩 TABLE_1,则该表将移动到表空间中空余空间开始的位置,高水位标记将会大大降低。图 6 展示了对 TABLE_1 再次进行重组和压缩后表空间的变化。
图 6. 对表 TABLE_1 再次执行重组和压缩如何降低表空间的高水位标记![对表 TABLE_1 再次执行重组和压缩如何降低表空间的高水位标记](https://i-blog.csdnimg.cn/blog_migrate/5328cf35f4f14a14bb11625c80806107.png)
注 意,图 4、图 5、图 6 中的示例的假设前提是:已经创建了 TABLE_1、 TABLE_2、 TABLE_3 和 TABLE_4,一次填充一个,并且表空间 TBSP1 是完全紧凑的。实际上,这些例子表示的是最糟的情况。当一个表空间中存在多个表时,更可能出现的情况是,整个表空间的不同表之前存在间隙。评估存在的范围 片段的级别将更加复杂,但不像这几个例子那么极端。因此,实际的高水位标记影响可能不会那么明显。
向同一个表 空间开始添加索引对象和大对象 (LOB) 时,很难预测究竟会发生什么情况。可以使用命令 db2dart /DHWM 显示表空间中所有表的范围布局,使用命令 db2dart /LHWM 解释该布局并生成一组告诉您如何降低高水位标记的步骤。但是,惟一能够保证布局尽可能紧凑的方法是从头重新构建整个表空间——卸载并重新加载它的表。只有 这样才能将压缩回收的所有存储空间返回给操作系统。
![]() ![]() |
![]()
|
深 度压缩帮助减少保存表数据所需的存储空间。更多压缩后的行可以存储在一个页面上,因此深度压缩还能够提高 I/O 密集型系统的查询性能(对于 CPU 密集型系统则不一定如此)。但是,从包含压缩表的 DMS 表空间回收空间所需的过程执行起来非常繁琐,可能会影响数据库的可用性。
使用 Inspect 工具为表构建压缩字典时,相应表空间的高水位标记不会受到影响。如果希望将收回的存储空间返回给文件系统以供重新分配,可以使用此方法压缩现有表。在各自的表空间中存储每个表也能使空间回收更加方便。
IBM 的深度压缩之旅远远没有结束。“Viper 2”将推出一个全新的深度压缩功能,包括一个名为 Automatic Dictionary Creation 的功能。在下次专栏文章中我将对此功能和其他增强功能进行说明。
特 别感谢 IBM Toronto Lab 的 Bill Minor (Data Management Services) 和 Kelly Schlamb (Data Protection Services and Backup/Restore Development) 为本文提供的帮助。
![]() ![]() |
![]()
|
- 本文从 IBM Database Magazine 期刊(原 DB2 Magazine)取得授权并进行翻译,参见 IBM Database Magazine 站点 上的 英文原文。
- 下载 DB2 V9 试用版体验 DB2 最新的技术特性。
- 通过访问 developerWorks 中国 Information Management 专区 的 DB2 9 技术资源中心获得更多的文章、教程和多媒体课件等学习资源。
- 通过访问 alphaWorks获得更多 IBM 的前瞻性技术和资源。
- 通过访问 IBM Database Magazine 站点 community 专题获得更多用户体验和交流信息。