转自http://www.ibm.com/developerworks/cn/data/dmmag/dbt13n1/dbt13n1_distdba/index.html?ca=drs-
DB2 9.5 改进了深度压缩技术,进一步节省空间和提高性能
简介: 在前一篇专栏文章 “DB2 深度压缩,第 1 部分” 中,我提到企业数据库的增长速度大约是每年 125%。随着数据库的增长,保存、保护、分布和利用数据库中数据的需求也在增长。为了帮助减少不断增长的数据库的存储需求,IBM 在 DB2 9 中引入了深度压缩技术。在 DB2 9.5 中根据客户的反馈进一步改进了这种技术。在本文中,我将介绍 DB2 9.5 中新的压缩特性。
来自 IBM Database Magazine 。
Automatic Dictionary Creation(ADC)
尽管在创建表时可以为它启用深度压缩,但是在表中填充数据之前,无法构建压缩词典。在 DB2 9 中,只有两种构建压缩词典的方法:一种方法是对已经启用压缩的填充了数据的表进行重组(执行 REORG 命令并指定 KEEPDICTIONARY 或 RESETDICTIONARY 选项);另一种方法是,估算一个填充了数据的表由于使用压缩能够获得多大好处(执行 INSPECT 命令并指定 ROWCOMPESTIMATE 选项)。
只有根据所有相关数据构建压缩词典,才能获得最好的压缩率。通过表重组(或使用 Inspect 实用程序)构建压缩词典,会获得很高的压缩率,因为在构建压缩词典时使用了表中的每一行。但是,IBM 的测试表明,只分析少量有代表性的数据,也可能获得良好的压缩率。(在某些情况下,仅仅分析总行数的 1%,就能够获得 45% 的压缩率。)这一现象构成了新的压缩特性 Automatic Dictionary Creation(ADC)的基础。
在 DB2 9.5 中,如果在创建一个表时启用了压缩,那么一旦表中存储了足够的数据,ADC 就会自动构建压缩词典。ADC 启动压缩词典构建过程的阈值依赖于表的行大小。在通常情况下,当为表分配了 1-2MB 的页面时,就开始构建词典。当达到这个阈值时,ADC 会检查表中包含多少用户数据;如果数据至少有 700KB,就会构建压缩词典。(注意,这些值是在内部设置的,不能修改。)可能触发 ADC 的操作包括插入、导入、装载和跨分区重新分布数据。
与 Inspect 实用程序构建的压缩词典一样,通过 ADC 创建的词典也存储在表中现有数据后面。表中原有的记录并不压缩,直到执行离线表重组操作,或者更新原有的记录(在这种情况下,在保存修改时对修改的每个记录进行压缩)。新记录在添加时进行压缩。(ADC 的目标之一是,构建压缩率比较好的压缩词典,同时避免在表中存储大量未压缩的数据。)图 1 显示,在创建时启用压缩的表在 ADC 构建压缩词典之前、期间和之后的情况。
在为已经填充数据的表启用压缩时(把 COMPRESS 属性设置为 ON),并不自动创建压缩词典。相反,在下一次发生表增长操作时,会触发 ADC 并使用表中开头的少量记录构建压缩词典。创建词典之后,对后续的插入、导入、装载和重新分布操作在表中添加的数据进行压缩;原有的数据仍然不压缩。
正如您看到的,压缩词典的自动创建受到表的压缩属性的影响。如果希望禁止 ADC,那么先不要为表启用压缩,直到您已经准备好手工构建压缩词典并压缩数据。另一方面,如果希望利用 ADC,那么要记住,与通过离线表重组创建的压缩词典相比,ADC 产生的词典的压缩率可能不太好。另外,因为在构建压缩词典时表仍然在线,在达到阈值并触发 ADC 时,触发 ADC 的事务的性能可能会受影响。
DB2 9.5 中的另一个重要变化是,改变了在启用深度压缩的表上执行装载操作的方式。在 DB2 9 中,如果已经为表创建了压缩词典,那么 Load 实用程序在装载数据时用这个词典压缩数据。但是,如果还没有压缩词典,那么 Load 实用程序并不在装载操作过程中创建词典。在 DB2 9.5 中,如果装载启用压缩的表并执行 LOAD REPLACE 操作,Load 实用程序可以构建压缩词典。启动这种操作的方法是执行 LOAD 并指定 REPLACE KEEPDICTIONARY 或 REPLACE RESETDICTIONARY 选项。(如果装载的表启用了压缩,而且达到了触发 ADC 的数据量,那么 LOAD INSERT 操作也可以导致创建压缩词典。)
如果执行带 REPLACE KEEPDICTIONARY 或 REPLACE RESETDICTIONARY 选项的 LOAD 命令,而压缩词典不存在,就会创建一个新词典。如果使用 KEEPDICTIONARY 选项,那么构建压缩词典所需的数据量由 ADC 的策略决定。因此,会在表中存储一些未压缩的数据;创建词典之后,使用新词典压缩装载的其他数据。但是,如果指定 RESETDICTIONARY 选项,那么构建词典所需的数据量不由 ADC 的策略决定,装载一行之后就可以构建压缩词典。
如果执行带 REPLACE KEEPDICTIONARY 或 REPLACE RESETDICTIONARY 选项的 LOAD 命令,而压缩词典已经存在,那么将重新创建现有的词典(RESETDICTIONARY)或按原样保留它(KEEPDICTIONARY),并用现有词典或新词典压缩表中的数据。
如果希望在执行装载操作的同时为启用压缩的 EMPLOYEE 表创建新的压缩词典,应该执行清单 1 中的命令。
LOAD FROM datafile.del OF DEL REPLACE RESETDICTIONARY INTO employee |
在执行这个命令时,如果 EMPLOYEE 表的压缩词典不存在,DATAFILE.DEL 文件中的一些记录会不经压缩装载到 EMPLOYEE 表中。装载了 1-2MB 的数据之后,ADC 使用这些数据构建压缩词典;然后使用这个压缩词典压缩余下的记录并写入表中。
为了帮助评估深度压缩对表的效果,DB2 9.5 中还引入了 ADMINTABCOMPRESSINFO 管理视图和 ADMIN_GET_TAB_COMPRESS_INFO 表函数。表 1 给出 ADMINTABCOMPRESSINFO 管理视图的结构。
ADMIN_GET_TAB_COMPRESS_INFO 表函数为 ADMINTABCOMPRESSINFO 管理视图提供一个编程接口,可以在 SQL 查询中嵌入对这个函数的调用。这个函数的语法是:
ADMIN_GET_TAB_COMPRESS_INFO (TableSchema, TableName, ExecMode)
表 1. ADMINTABCOMPRESSINFO 管理视图
列名 | 数据类型 | 说明 |
TABSCHEMA | VARCHAR(128) | 模式名 |
TABNAME | VARCHAR(128) | 表名 |
DBPARTITIONNUM | SMALLINT | 数据库分区号 |
DATA_PARTITION_ID | INTEGER | 数据分区号 |
COMPRESS_ATTR | CHAR(1) | 表的 COMPRESS 属性的状态,可以是以下值之一: ‘Y’ 表示 Row compression 设置为 YES ‘N’ 表示 Row compression 设置为 NO |
DICT_BUILDER | VARCHAR(30) | 构建压缩词典采用的代码路径,可以是以下值之一: ‹NOT BUILT› 表示没有词典 ‹INSPECT› 表示 INSPECT ROWCOMPESTIMATE ‹LOAD› 表示 LOAD INSERT/REPLACE ‹REDISTRIBUTE› 表示 REDISTRIBUTE ‹REORG› 表示 REORG RESETDICTIONARY ‹TABLE GROWTH› 表示 INSERT、IMPORT(使用 INSERT 的 IMPORT)或者导致 DB2 把更新的记录放在新页面上的更新操作 |
DICT_BUILD_TIMESTAMP | TIMESTAMP | 构建压缩词典的日期和时间(如果没有词典,时间戳就是 NULL。) |
COMPRESS_DICT_SIZE | BIGINT | 压缩词典的大小,以字节为单位。 |
EXPAND_DICT_SIZE | BIGINT | 扩展词典的大小,以字节为单位。 |
ROWS_SAMPLED | INTEGER | 构建词典时使用的记录数。对于带着压缩词典迁移的表,这个列的值是 NULL。 |
PAGES_SAVED_PERCENT | SMALLINT | 通过压缩节省的页面的百分比。这一信息只基于取样缓冲区中的记录数据。对于带着压缩词典迁移的表,这个列的值是 NULL。 |
BYTES_SAVED_PERCENT | SMALLINT | 通过压缩节省的字节的百分比。这一信息只基于取样缓冲区中的记录数据。对于带着压缩词典迁移的表,这个列的值是 NULL。 |
AVG_COMPRESS_REC_LENGTH | SMALLINT | 构建词典时使用的记录压缩后的平均长度。对于带着压缩词典迁移的表,这个列的值是 NULL。 |
其中:
- TableSchema 指定压缩信息所针对的表所在的模式。
- TableName 指定压缩信息所针对的表。
- ExecMode 指定在执行这个函数时使用的模式。如果这个参数设置为 REPORT(默认值),就会获取现有的压缩统计数据。如果这个参数设置为 ESTIMATE,就会根据指定的表中的当前数据生成新的压缩统计数据;返回的结果反映了如果马上对这个表进行压缩,将产生的压缩效果。
例如,如果希望获取并显示在压缩 PAYROLL.STAFF 表时生成的压缩统计数据,应该执行下面这样的查询:
SELECT * FROM TABLE(SYSPROC.ADMIN_GET_TAB_COMPRESS_INFO (‘payroll’, ‘staff’, ‘REPORT’)) AS comp_info; |
另一方面,如果希望使用表中当前存储的数据估计并显示 PAYROLL.STAFF 表的压缩统计数据,应该执行下面这样的查询:
SELECT * FROM TABLE(SYSPROC.ADMIN_GET_TAB_COMPRESS_INFO (‘payroll’, ‘staff’, ‘ESTIMATE’)) AS comp_info; |
第一个查询报告执行的最后一次压缩操作的效果;第二个查询可以指出,通过生成新的压缩词典并重新压缩数据,是否可以改进压缩的效果。数据会随着时间变化,所以应该定期执行这两个查询,了解压缩的效果。
从 DB2 9.5 开始,小于等于 32KB 的 XML 文档可以存储在基表的行中,而不需要使用默认的 XML 存储对象。(更大的文档必须存储在默认的 XML 存储对象中。)如果您主要操作小的 XML 文档,那么以“内联”方式存储它们会显著提高性能。这是因为对直接存储在基表行中的 XML 文档进行查询、插入、更新或删除所需的 I/O 操作更少。
内联存储 XML 文档的另一个好处是,文档本身可以受益于深度压缩。这是因为深度压缩在基表上执行,而“内联的”XML 文档存储在基表行中。因为在创建压缩词典时会在给定列中寻找重复出现的子字符串,所以如果 XML 文档有许多相似的内容,就非常适合进行压缩,这会减少所需的存储空间并提高 I/O 效率。
DB2 9 中引入的深度压缩有助于减少存储表数据所需的空间。经过压缩之后,可以在一个页面中存储更多的行,所以在有 I/O 瓶颈的系统上,深度压缩还可以提高查询性能(在有 CPU 瓶颈的系统不一定有这种效果)。DB2 9.5 对深度压缩做了一系列改进,使我们能够更轻松地为新表实现压缩和评估压缩对表的效果。DB2 9.5 还允许在批量装载大量数据时使用压缩。由于数据库以每年 125% 的速度增长,在未来的 DB2 版本中很可能会提供效果更好的深度压缩功能。
感谢 IBM 多伦多实验室的 Data Management Services 经理 Bill Minor,他向我提供了关于 DB2 9.5 中新的深度压缩特性的详细信息,并审阅了本文。