DB2 9.7 新特性 - 内联 LOB 的使用

红薯 发布于 2010/08/08 22:36
阅读 1K+
收藏 1

DB2 9.7 LOB 介绍

大对象(LOB),指 DB2 中的一类数据类型。它对应于 DB2 中的数据类型有三种:BLOB 数据类型存储二进制数据,比如图片。CLOB 数据类型存储字符数据,比如文本文件。DBCLOB 数据类型存储双字节字符数据。大对象数据类型对应的存储物体有可能是很大的图片或者文件,与其他数据类型相比,大对象在 DB2 中需要采用特殊的存储方式。


图 1. 传统 LOB 存储方式
图 1. 传统 LOB 存储方式

因为大对象的大小一般都很大,甚至大于 DB2 中最大行大小。也就意味着很多大对象无法与基本表行存储在一起。DB2 为了解决这个问题,采用如图 1 所示的存储方式,大对象被存放于特定的大对象表空间中,原来表行中大对象的位置存放一个 LOB 描述符,指向大对象所存储的位置。因为大对象与基本表行存储于不同位置,处理大对象数据就会变得困难。

什么是内联 LOB

出于对大对象大小会大于表最大行大小的考虑,DB2 采用了分开存储的方式。然而在有些情况下,大对象的大小并不是非常大,此类大对象完全可以存放在数据表行中以提高大对象的数据访问性能。DB2 9.7 中,支持以直接插入表行的方式来存储比较小的大对象,这就是内联 LOB 技术。


图 2. 内联 LOB 存储方式
图 2. 内联 LOB 存储方式

如图 2 所示,表行中直接存放了一个图形文件的大对象(BLOB)和一个文本文件的大对象(CLOB)。在数据访问过程中,就没有访问其他存储空间的环节。

如何确定一个大对象是否能够以内联的方式存储,是由表定义中新的 INLINE LENGTH 选项决定的。如果表采用了内联 LOB 存储方式,那么在存储过程中,小于 INLINE LENGTH 设定值的大对象则直接存放于基本表空间中,大于 INLINE LENGTH 设定值而无法以直接插入方式存储的 LOB 值将单独存储在 LOB 存储器对象中。

INLINE LENGTH 的大小限制

INLINE LENGTH 选项是 DB2 9.7 中表定义的特殊属性,用以限定直接插入表行的存储方式可以插入的最大大对象的大小。INLINE LENGTH 的大小显然不会大于最大行大小。因为超出最大行大小的大对象是无法存储于基本表中,这一点是不能避免的。最大行的大小是与页大小相关的,如果是 32K 的数据页,那么对应的表中的行的最大大小是 32677 字节。但是,对于每个直接插入表行的大对象,需要 4 字节的额外开销,也就是说能够直接插入的最大 LOB 大小是 32673 字节。

INLINE LENGTH 的设置

在 DB2 9.7 中,启用内联 LOB 的方法就是在创建表或者修改表时定义 INLINE LENGTH 的值。启用内联 LOB 的方式有两种:

  • 隐式启用:在新表被创建时所有的 LOB 列会启用此功能。如果是旧表被修改,添加的所有 LOB 列会启用此功能。如果是数据库升级,那么数据库中所有表的 LOB 列会隐式启用此功能。LOB 列隐式启用此功能时,INLINE LENGTH 的值也是默认定义的。前文中讲过 LOB 描述符的定义。参考图 1。INLINE LENGTH 的隐式设定值的大小就是原先 LOB 描述符的大小。这也很好理解。隐式启用的 LOB 不会过多的改变原先的存储方式。但是小于 LOB 描述符大小的大对象如果还存储于不同的表空间中显然是多浪费了相当于一个 LOB 描述符大小的空间。
  • 显式启用:可以通过使用 CREATE TABLE 语句或 ALTER TABLE 语句来显式地定义 INLINE LENGTH 的大小。

使用内联 LOB 技术

本文将以一张案例表使用内联 LOB 技术的过程,阐述如何监控和管理内联 LOB 存储方式。其中会使用到 DB2 9.7 中新的有关于内联 LOB 的列函数 admin_est_inline_length 和 admin_is_inlined,系统表 sysibm.syscolumns 的新增列 inline_length 等新内容。为了便于对比内联 LOB 技术的效用,在对表操作之前,先做一个数据库的备份。

查看目标表信息

对于目标表,为了更有效的验证内联 LOB 技术带来的好处,需要获得表的一些基本信息。采用内联 LOB 可以节省存储空间,因为没有了 LOB 描述符的空间开销。而且当基本表启用了深度压缩后,存于基本表中的大对象也可以被压缩而节省空间。首先来获得目标表大小的基本信息。


清单 1. 目标表大小信息

				
# db2 "SELECT varchar(tabname,15) as TABLENAME, data_object_p_size, lob_object_p_size,
(data_object_p_size + lob_object_p_size) as total_p_size FROM TABLE
(SYSPROC.ADMIN_GET_TAB_INFO('KONGZAIHUA', 'LOBTAB1')) AS T"

TABLENAME DATA_OBJECT_P_SIZE LOB_OBJECT_P_SIZE TOTAL_P_SIZE
--------------- -------------------- -------------------- --------------------
LOBTAB1 1024 2828829312

 

通过表函数 ADMIN_GET_TAB_INFO 可以获得目标表 LOBTAB1 的基本信息,其中 data_object_p_size 是表中常规数据的物理大小,lob_object_p_size 是大对象数据的物理大小。它们的和就是表中数据所占用的实际存储开销。实际表的存储开销还包括索引的存储开销等,但与本主题无关,这里不做统计。


清单 2. 目标表 INLINE LENGTH 信息

				
# db2 "select varchar(name,15) as COLNAME, inline_length, coltype
from sysibm.syscolumns where tbname = 'LOBTAB1'"

COLNAMEINLINE_LENGTH COLTYPEPCTINLINED
--------------- ------------- -------- ----------
AUTHOR 0 VARCHAR-1
CHANGEDBY 0 VARCHAR-1
CHANGEDON 0 VARCHAR-1
CREATEDON 0 VARCHAR-1
DATA 276 BLOB1
DATA_VERSION 0 VARCHAR-1
DOCUID 0 VARCHAR-1
ENHSPOT 0 VARCHAR-1
GENERATED 0 VARCHAR-1
INTERNAL 0 VARCHAR-1
SHORTTEXTID 0 VARCHAR-1
TOOL_TYPE 0 VARCHAR-1
VERSION 0 VARCHAR-1

13 条记录已选择。

 

INLINE_LENGTH 和 PCTINLINED 是 DB2 9.7 中系统表 sysibm.syscolumns 的新增列。记录了 LOB 列设定的 INLINE LENGTH 的大小和内联的百分比。本案例表 LOBTAB1 中,列 DATA 的数据类型是 BLOB,已经设定的 INLINE LENGTH 大小是 276. 这个值是在创建表时隐式赋予 LOB 列,它的大小等于 LOB 描述符的大小。因为 INLINE LENGTH 的大小就是原先需要的 LOB 描述符的大小,这样的设定不会很大的改变表中所有 LOB 的存储结构,除非大部分的 LOB 都小于 LOB 描述符的大小。清单 2 中显示,在隐式设定 INLINE LENGTH 值的情况下,PCTINLINED 的值是 1. 也就是只有百分之一甚至更少的 LOB 被直接存储在基本表中。这种几乎没有多少大对象被内联的情况,正适合与很多大对象被内联的情况向对比,来验证内联 LOB 的效果。


清单 3. 目标表隐式内联信息

				
C:\>db2 "select count(admin_is_inlined (DATA)) as t from KONGZAIHUA.LOBtab1
where admin_is_inlined (DATA) = 1"

T
-----------
32

1 条记录已选择。


C:\>db2 "select count(*) from KONGZAIHUA.LOBtab1

1
-----------
4348

 

1 条记录已选择。

从清单 3 可以看出,只有 32 条行记录中直接存储了小 LOB,而表共有 4348 条记录。与清单 2 中的内联百分比大致对应。

查看目标表压缩后信息

对目标表采用深度压缩,重组表,获取并记录目标表启用压缩后的大小信息。关于如何启用深度压缩的内容,可以参考 IBM 信息中心的文档,本文中不再细表。


清单 4. 目标表压缩后信息

				
# db2 "SELECT varchar(tabname,15) as TABLENAME, data_object_p_size, lob_object_p_size,
(data_object_p_size + lob_object_p_size) as total_p_size FROM TABLE
(SYSPROC.ADMIN_GET_TAB_INFO('KONGZAIHUA', 'LOBTAB1')) AS T"

TABLENAME DATA_OBJECT_P_SIZE LOB_OBJECT_P_SIZETOTAL_P_SIZE
--------------- -------------------- -------------------- --------------------
LOBTAB1 512 2828828800

 

丢弃数据库,用之前做的备份来恢复数据库。目标表被恢复到压缩之前。准备显示设置 INLINE LENGTH 的大小以便更有效的使用内联 LOB 功能。

评估 INLINE LENGTH 设定值

注意:设定的 INLINE LENGTH 的大小只能变大,不能再修改表定义时减小。如何设定 INLINE LENGTH 的大小,需要根据实际应用情况选择合适的值。虽然对此没有什么标准,但是 DB2 还是提供了有用的工具 admin_est_inline_length 来估算需要的 INLINE LENGTH 的大小。


清单 5. 内联 LOB 估算信息

				
C:\>db2 "select admin_est_inline_length(DATA) as t
from KONGZAIHUA.LOBtab1"

T
-----------
3525
3533
3557
3557
3525
7102
……

 

如清单 5 所示,函数 admin_est_inline_length 能够返回每个记录直接存储 LOB 需要的 INLINE LENGTH 的大小。可以通过 MAX,AVG 等函数来处理估算的值,选择 INLINE LENGTH 的大小来设置。本次案例中,为了更好的显示内联 LOB 的功能,选取了一个比较大的估算值 7527,这样大部分的 LOB 都会被内联存放。

显式设置 INLINE LENGTH

通过 CREATE TABLE 或者 ALTER TABLE 命令自定义 INLINE LENGTH 的大小。


清单 6. CREATE TABLE 语法

				
>>-CREATE TABLE--table-name------------------------------------->
|--column-name--+ '-| data-type |-----'+--+--------------------+---|
+-INLINE LENGTH--integer---------------------------------------+---|

 

创建 TABLE 的过程中,对于 LOB 列可以使用 INLINE LENGTH integer 指定大小。清单 6 列出了与此设定相关的语法。本次案例是对已有表操作,通过实际案例来解释 ALTER TABLE 命令的相关语法。


清单 7. 目标表启用内联 LOB

				
C:\>db2 "ALTER TABLE KONGZAIHUA.LOBtab1 ALTER COLUMN DATA
SET INLINE LENGTH 7527"
DB20000ISQL 命令成功完成。

 

如清单 7 所示,ALTER TABLE 命令可以修改 LOB 列的 INLINE LENGTH 来指定大小。目标表的 INLINE LENGTH 被设置为 7527. 设置完 INLINE LENGTH 的值后,还需要重组表使之生效。

重组表使新设定生效

对于内联 LOB 功能,DB2 9.7 中表重组功能也相应做了扩充,REORG 命令多了 LONGLOBDATA 参数。LONGLOBDATA 参数只对 long 和 LOB 列有效。默认情况下是不启用 LONGLOBDATA 的,因为对 long 和 LOB 列的重组很消耗时间。但是转换分开存放的 LOB 到内联的 LOB 就需要这个参数。


清单 8. 重组目标表

				
C:\>db2 "REORG TABLE KONGZAIHUA.LOBtab1 LONGLOBDATA"
DB20000IREORG 命令成功完成。

 

正如前面的解释,如果表特别大,LOB 的重组可能会使用一定的时间。等表重组完成后,内联 LOB 的启用也就完成了。

查看目标表重组后信息

与重设 INLINE LENGTH 大小之前所做的一样,获取同样的目标表信息。首先获取并记录目标表的大小信息。


清单 9. 目标表大小信息

				
# db2 "SELECT varchar(tabname,15) as TABLENAME, data_object_p_size, lob_object_p_size,
(data_object_p_size + lob_object_p_size) as total_p_size FROM TABLE
(SYSPROC.ADMIN_GET_TAB_INFO('KONGZAIHUA', 'LOBTAB1')) AS T"

TABLENAME DATA_OBJECT_P_SIZE LOB_OBJECT_P_SIZETOTAL_P_SIZE
--------------- -------------------- -------------------- --------------------
LOBTAB1 20736 806428800

 

清单 9 中,基本表的大小与清单 1 想比变大了,而 LOB 的大小相比之下变小了。这正说明了很多的 LOB 被直接放入到基本表中,被作为基本表统计了。总的大小相比减少了。


清单 10. 目标表 INLINE LENGTH 信息

				
C:\>db2 "select varchar(name,15) as COLNAME, inline_length, coltype
from sysibm.syscolumns where tbname = 'LOBTAB1'"

COLNAMEINLINE_LENGTH COLTYPE
--------------- ------------- --------
AUTHOR0 VARCHAR
CHANGEDBY0 VARCHAR
CHANGEDON0 VARCHAR
CREATEDON0 VARCHAR
DATA7527 BLOB
DATA_VERSION0 VARCHAR
DOCUID0 VARCHAR
ENHSPOT0 VARCHAR
GENERATED0 VARCHAR
INTERNAL0 VARCHAR
SHORTTEXTID0 VARCHAR
TOOL_TYPE0 VARCHAR
VERSION0 VARCHAR

13 条记录已选择。

 

与清单 2 对比,清单 9 中查询到目标表的 INLINE LENGTH 值已经变成了设定的 7527,修改生效。


清单 11. 目标表显式内联信息

				
C:\>db2 "select count(admin_is_inlined (DATA)) as t from KONGZAIHUA.LOBtab1
where admin_is_inlined (DATA) = 1"

T
-----------
3902

1 条记录已选择。

 

与清单 3 对比,清单 11 中显示内联的 LOB 有 3902 条之多,说明非常多的 LOB 被直接存放在了表中,内联的效果很明显。

查看内联目标表压缩后信息

最后,如先前一般,对目标表进行压缩,以重置数据字典的方式重组表。完成后获取压缩后的表大小信息。


清单 9. 目标表大小信息

				
# db2 "SELECT varchar(tabname,15) as TABLENAME, data_object_p_size, lob_object_p_size,
(data_object_p_size + lob_object_p_size) as total_p_size FROM TABLE
(SYSPROC.ADMIN_GET_TAB_INFO('KONGZAIHUA', 'LOBTAB1')) AS T"

TABLENAME DATA_OBJECT_P_SIZE LOB_OBJECT_P_SIZETOTAL_P_SIZE
--------------- -------------------- -------------------- --------------------
LOBTAB1 3072 806411136

 

分别与清单 1,清单 4,清单 9 比较,最后的表的总大小变化很大,恰恰验证了存放于基本表中的 LOB 被压缩的效果是非常明显的。下面是根据这几张清单列出来的效果图。


图 3. 存储开销对比图
图 3. 存储开销对比图

如图 3 所示,如果没有采用内联 LOB 技术,LOB 存放在分开的表空间中是不会被压缩的。深度压缩只会压缩存储与基本表中的数据。本案例中采用内联 LOB 后,总的大小与不采用内联 LOB 压缩后的大小相同。这虽然只是一种巧合,但还是说明采用内联后,表的总大小变小了。在不启用压缩的情况下,内联 LOB 节省空间的好处还不是很明显。采用了内联 LOB 并压缩后的效果非常惊人,案例表的存储开销只用了原先存储的 38%。

内联 LOB 的性能

内联 LOB 减少存储开销的好处已经在本次应用中得到了体现。这是内联 LOB 影响的一方面。内联 LOB 影响的另外一方面是提高访问 LOB 数据的查询的性能。

  • LOB 分开存放于不同的表空间中,对 LOB 的查询不但要访问基本表,还需要访问 LOB 表空间,查询的开销很大,往往会造成应用程序中的瓶颈。内联 LOB 可以解决这样的问题,对 LOB 的查询只需要直接访问基本表,不需要执行附加的 I/O。
  • 内联的 LOB 可以被压缩。深度压缩技术对于性能的影响同样适用于此。访问压缩后的数据提高了 I/O 的利用,查询性能也会得到提高。

内联 LOB 确实可以提高对 LOB 查询的性能,但在应用的过程中还需要注意。因为 LOB 数据被存放在表行中,也就是说原先的行记录大小增加了,这样在数据页中存放的行记录数目就变少了。这样很可能会影响非 LOB 查询的性能,因为一个查询或许会需要读入更多的数据页才能完成检索。所以在实际应用过程中需要权衡,如果应用程序对非 LOB 查询的性能要求很高,则慎重考虑是否使用该项技术。

总结

本文阐述了 DB2 9.7 的内联 LOB 技术原理和实现。相比于传统的存储 LOB 技术,提供了可选择的存储方式,帮助提高处理大对象的性能,减少存储开销。但是同时,内联 LOB 技术是一把双刃剑。内联 LOB 的使用有一定的限制,也有可能会影响到非 LOB 处理的性能。所以在实际应用中,需要根据对数据表的实际操作侧重点,斟酌如何使用好内联 LOB 技术。

加载中
返回顶部
顶部