级别: 初级 developerWorks 中国网站编辑团队, 编辑, IBM
2009 年 4 月 09 日 第 1 部分中提到的样例场景中的第一个挑战就是插入大量的 FpML 交易到 DB2 中。本文描述了向一个 DB2 数据库中有效添加 XML 数据技术。
高性能地插入 XML 文档
DB2 VERSION 9.5 向把 XML 数据迁移进 DB2 表中提供了 3 个选项:插入,导入和装载。从调优的角度来看插入和导入有类似的特点,因为导入实用工具事实上就是执行了一系列插入操作。
提示:装载实用工具的优势对 XML 和对关系型数据都一样:数据不需要记录日志而且是自动启用并行来提高性能。 DB2 基于 CPUs 数目和表空间容器来判断一个默认并行度。在其它方面,导入和插入的好处是数据可以在其它事务正在运行的时候插入到表中,所有约束都会被校验,而且触发器也会生效。
在某些情况下通过执行有中间过渡表的 ETL 操作来装载 XML 数据到一个中间过渡表和填充实际目标表是有很多好处的。
你是否使用插入、导入或装载,应用下面性能指南:
- 作为一个关键的前提条件,确保 DMS 表空间使用大页面大小,比如 16KB 或者 32KB 。
- 即使如果你没有在目标表上定义任何索引,为了高效的 XML 存储访问,DB2 pureXML 存储机制会显式的维护域和路径索引。因此你应该提供足够的缓冲池空间以支持索引读取。
- 如果你有多个用户定义 XML 索引,那么通常在没有任何数据插入的情况下定义它们要比之后再定义更好。在插入过程中,每个 XML 文档将只被处理一次,以对所有 XML 索引生成索引输入。然而,如果你在之后执行了多个 CREATE INDEX 语句,在这个 XML 列中的所有文档都会被读取多次。
另外,对插入和导入操作考虑下面的指南:
- 增加日志缓冲大小(LOGBUFSZ)和日志文件大小(LOGFILESIZ)有助于提高插入性能。这对 XML 插入非常重要,因为每行的数据量会比关系型数据要大很多。推荐使用一个快速 I/O 设备来存放日志。
- 如果你使用插入,一个小的 COMMITCOUNT 值参数也会影响性能。每 100 行或更多行一提交将比每行都提交拥有更好的性能。你可也可以省略 COMMITCOUNT 参数让 DB2 在恰当的时候提交
- ALTER TABLE < 表名 > APPEND ON 语句对这个表启用追加模式。新数据被追加到表的最后而不是在现有页面中搜索空闲空间。更多细节和指南见 DB2 文档。
把大型 XML 文档拆分成更小的片段
如果需要转换或移动的 XML 文档的数量很多,常常是把它们联合成一个大型的 XML 文档。处理一个大型文档常常要比处理上千个琐碎文件要容易。图 9 显示了一个 XML 文档的结构,这个文档使用根元素 <alltrades> 来压缩一批 FpML 文档。
提示:当你收到这样一个“复合文档”,你会希望把它分拆为单独的交易并在 TRADES 表中的每一行都插入一个交易文档。这将提供比存储在一个复合文档片段中更好的查询和更新性能。
清单 1. 复合 XML 文档结构
<FpML>
<trade>
...
</trade>
</FpML>
<FpML>
<trade>
...
</trade>
</FpML>
...
<FpML>
<trade>
...
</trade>
</FpML>
|
DB2 可以添加最大 2GB 的 XML 文档,而且你可以拆分 2GB 的文档为更小的文档,如图 10 所示。在插入语句中的 XMLTABLE 函数为每个交易(每个 <FpML> 元素)在一行中生成一个单独的 XML 类型列。“ ? ”在前面的子句中表示一个参数标记给这个语句中提供了一个 XML 文档输入。 cast (? as XML) 是用来表示 XML 类型的参数标记。
XML 数据模式需要解析,有良好格式的 XML 文档有一个文档节点(作为这个文档中的唯一根元素的父节点)。这个文档节点在一个 XML 文档的文本表示上并不可见。从输入文档中抽取的交易子树没有文档节点,而且不能作为一个有良好格式的文档插入。因此,document{} 构造器为每一个抽取出来的交易创建一个文档节点。
清单 2. 把大型输入文档拆分成单独的交易文档
INSERT INTO trades(tradedoc)
SELECT doc FROM
XMLTABLE ('$d/alltrades/FpML' passing cast(? as XML) as "d"
COLUMNS
doc XML PATH 'document{.}') AS X |
你可能记得 TRADES 表也有一个整型的 tradeId 列。这列没有被上述插入填充。基于你实际的应用需求,你可以定义 tradeId 列为自生成列。如果有 XML 列的表也包含关系型列,用从 XML 文档中抽取的值来填充它们可能很有好处。这会在下一章中进行讨论。
以混合方式存储交易
在图 11 中你可以看到一个 TRADES 表的第二个版本,在关系型列中保留了交易时间、交易类型和各个交易方的 IDs 。这是除了在 XML 列中的全部 FpML 文档外的关系型数据,因此叫做混合存储。
提示:抽取选择的 XML 元素值插入到同一行的关系列中,XML 文档可以满座多种需求。关系型列可以很容易的被 SQL-only 访问重要或经常访问的数据条目、定义的主键、外键或其它约束,以及多列关系型索引(组合键)的定义。
清单 3. FpML 交易的混合存储
create table trades2 (trdDate Date, trdType varchar(20), partyId1 integer,
partyId2 integer, tradedoc XML);
insert into trades2
select *
from xmltable('$d/FpML' passing cast(? as XML) as "d"
columns
tradeDate date path 'trade/tradeHeader/tradeDate',
tradetype varchar(20) path 'trade/*[2]/local-name(.)',
partyId1 integer path 'party[@id="party1"]/partyId' ,
partyId2 integer path 'party[@id="party2"]/partyId',
doc XML path 'document{.}')
) as t; |
在图 11 中的插入语句从文档中为我们的关系型列正确的抽取了那些条目。因此,这些在关系型列中的值和 XML 列中的 XML 文档是冗余的存储。
提示:要确保 XML 列和关系型列的一致性,你可以把这个插入语句包装进一个只把 FpML 文档当作输入参数的存储过程中。如果所有的插入都通过存储过程执行,那么每一行的数据将保持一致。这同样可以通过更新完成。应该避免插入和更新只对关系列进行操作。
插入时确保 XML 数据的品质
要确保 XML 文档的数据质量的首选方法是在 DB2 中注册一个正确的 XML 模式并在插入或更行的时候使用它来验证文档。在许多 XML 应用程序中,包括我们的 FpML 场景,XML 模式是随时间持续发展变化的。为了避免验证多种 FpML 文档输入,你肯需要在 DB2 中注册多个 FpML 模式版本,比如版本 4.1、4.2、4.3 和最终的 FpML5.0 。
记住,在 DB2 中依靠一个模式来验证 XML 文档是可以选择的。不过如果你不验证,在性能上和功能上也没有坏处。
提示:如果 XML 文档在应用层面已经被验证了,或者如果它们来自于同一个信任源,那么在 DB2 中对他们进行验证可能没有必要。在这种情况下你可能希望不进行验证就插入并节约验证过程中的额外 CPU 开销。
如果你选择在 DB2 层验证,你可以有很多方法。一个就是在一个插入语句中直接执行 XMLVALIDATE 函数,如图 12 所示。这非常灵活而且允许你在基于每个文档来控制验证。可以依靠各自对应的 FpML 模式版本来验证基于不同 FpML 标准版本的文档,而且仍然存在相同的 XML 列中。
清单 4. 在插入语句中直接验证交易文档
insert into trades (tradeID, tradedoc)
values (? , xmlvalidate(? according to xml schema ID matthias.fpml43)) |
这种方法的缺点是每个应用程序的每个插入语句都需要使用 XMLVALIDATE 函数并涉及正确的 XML 模式标识(这是在一个模式注册时分配的)。换句话说,用这个方法来保证数据质量是分散的责任而且没有集中控制。不过,DB2 有几个功能可以在允许的 XML 数据上添加更多的集中控制。
你可以定义检查约束来保证 XML 文档在它们未能通过 XMLVALIDATE 函数正确验证的情况下被拒绝。在图 13 中的第一个检查约束只有在使用 XMLVALIDATE 函数根据在 DB2 中注册的某个 XML 模式验证成功后才允许插入 XML 文档。验证失败的插入将被拒绝。第二个检查约束更强大,因为它只允许已经通过了被 IN 子句中列出的模式验证过的文档插入。如果在数据库中注册的仅有的 XML 模式是 matthias.fpml41、 matthias.fpml43、 matthias.fpml50 的话,这两种验证是等价的。
清单 5. 检查约束拒绝未验证文档
alter table trades add constraint chkvalidated1
check (tradedoc is validated)
alter table trades add constraint chkvalidated2
check (tradedoc is validated according to xmlschema id
IN (matthias.fpml41, matthias.fpml43, matthias.fpml50) |
检查约束他们自己不会执行或触发模式验证。他们只检查是否一个被插入(或更新)的文档已经被正确的验证过。
提示:不过,你可以使用 BEFORE 触发器来自动强制进行文档验证(图 14)。为了避免两次验证,我们推荐你在插入语句中显式的进行验证,或使用一个触发器,但不要同时用。
清单 6. BEFORE 触发器强制进行文档验证
create trigger tr1 before insert on trades
referencing new as n
for each row mode db2sql
begin atomic
set (n.tradedoc) = xmlvalidate(n.tradedoc according to
xmlschema id matthias.fpml43 );
end |
如果你已经在你的数据库中根据不同的模式验证了不同的文档,你可能碰到这样的情形,当你想找到用于验证一个文档的模式;或者,你希望找到一个确定模式来验证的所有文档。标量函数 XMLXSROBJECTID 可以为你做这些。你用一个 XML 文档(或者其中任意一个片段)作为一个数据被返回用于验证这个文档的 XML 模式的 ID 。有了这个 ID,你可以在 DB2 的 XML 模式库(XSR)找到 XML 模式。考虑下面的情况:
清单 7. 使用 XMLXSROBJECTID 函数
select xmlxsrobjectid(tradedoc)
from trades
where xmlexists...;
select T.tradedoc
from trades T, syscat.xsrobjects X
where xmlxsrobjectid(T.tradedoc) = X.objectid
and X.objectname = 'fpml43'; |
更多关于管理的个 XML 模式的文档的信息,请参见参考资源部分。
参考资料 学习
获得产品和技术
-
现在可以免费使用 DB2。下载 DB2 Express-C,这是为社区提供的 DB2 Express Edition 的免费版本,它提供了与 DB2 Express Edition 相同的核心数据特性,为构建和部署应用程序奠定了坚实的基础。
- 下载 信息管理软件试用版,体验它们强大的功能。
讨论
关于作者  | |  | developerWorks 中国网站编辑团。 |
对本文的评价
|