MRI 是 Multiple Row Insert 的简称,即多行插入。DB2 z / OS 自 V8 版起,都支持多行插入这一新特性。反复访问地址空间的代价十分巨大,MRI 可以减少这样的访问,使用 MRI 特性可以由多行插入合并成一个单一的操作集合从而减少这样的重复访问次数。在一个 SQL 操作中,插入多行数据可以被简称为行集。当对数据进行大批量数据插入时,通过这样的行集操作,会使对 DB2 的访问大大减少,从而提高性能。
DB2 的多行插入这个特别设计,目的是节省 CPU 并改进插入执行所需时间。在 z / OS 平台,Q APPLY 通过对 DB2 MRI 特性的支持,使得当应用数据中存在多行连续插入时 Q APPLY 的性能能有更显著的增强。在 Q 复制中这是一个非常理想的利用 DB2 特性的方案,它可以减少 MIPS (Million Instructions Per Second,即单字长定点指令平均执行速度) 成本并提高整体的性能。
图 1. 单行插入 VS 多行插入
Q APPLY 使用动态的嵌入式 SQL 更新 DB2。嵌入式 SQL 需要 SQL 描述符区域(SQLDA)输入数据到 DB2。使用多行插入时,需要在 SQL 描述符区域(SQLDA)中,对数据的每一列都提供一个输入数组,其中包含着要插入的数据的输入值。
Q APPLY 将在准备语句 ( PREPARE statement) 中指定的原子语句,然后统一一次性操作,但是如果插入此行集中任何一条插入语句失败,DB2 将会回滚所有已经更改的行集。然后,Q APPLY 将会从多行插入切换到单行插入模式来处理所有的插入操作,其中也包括最后一个引起报错的操作。错误将会被重试,并根据控制表中设置的 error actions 和 conflict actions 参数,适当地处理冲突和错误。
在应用多行插入特性时,SQL 语句需要为每个列行集输入提供一个连续的存储器阵列。Q APPLY 能够根据实际操作中行的大小,去动态决定每个插入操作中实际的插入行的数量。MRI 最终的目的是为了在给用户提供最佳的性能改进,同时避免额外的参数调整带来的操作的复杂性。
对于 Q APPLY,建议每组处理的行集不能超过 100 行。因为当行集中的行数超过 100 行时,MRI 特性带来的性能优势是可以忽略不计的, 在下面“QRep MRI 新特性的意义”章节中会做更详细解释。同时,在使用 MRI 特性时,由于需要占用更多的内存,所以额外设置一个内存需求限制,来支持此功能特性。
在同一个事务中,Q 复制将能够利用 MRI 对同一表做连续的插入操作,从而大大提升 CUP 性能。以一个向 non-partitioned 的表空间中插入 100000 行数据为例,实验表明使用 MRI 多行插入方式 CPU 的响应时间远低于使用单行插入的方式。实验表明,当每个行集有 10 行数据时,CPU 可以提升 35%;当每个行集中所需插入行数是 100 行或更多,CPU 可以改进 40%;当行集中行数更多时,CPU 的性能提升也是 40%左右,并没有更加显著的提升。所以建议对于 Q APPLY,每组处理的行集不能超过 100 行。同时,实验表明即使每个行集仅有 2 行数据,使用 MRI 亦能够极大地提高性能。
回页首
在使用多行插入特性时,所有数据都会进行预处理,首先要收集的上下文信息并确定事务是否有资格使用多行插入新特性。
一个允许应用多行插入特性的事务必须包含至少两个或更多的连续 INSERT 语句,而且这些 INSERT 必须是对同一个表的操作。如下图 2 就是对三个表的操作,其中对 T1 是一次多行插入 MRI, 对 T2 表的操作是一次单行插入 SRI,对 T3 表是一次多行插入 MRI。
图 2. 对多表的 MRI
当提交的事务满足 MRI 所需条件,Q APPLY 需要根据列的数量和大小,以及设置控制表中设置最大内存大小,去决定每组 INSERT 的最大行数。举个例子来说,假设参数 MRI 最小的插入行数设置为 5,用户设置 MRI AGENT 最大值为 1000 kb,对于行大小为 32 kb 的插入操作来说,行集的大小就是就是取建议行值 100 行和 1000kb/32kb=31 行两者的最小值,是 31。因此,所以在使用多行插入时,对于 32KB 大小的行,Q APPLY 将允许每个行集有约 31 行的数据,当然我们可以基于性能的测试结果,来调整这个值的大小。
然后 Q APPLY 会建立 SQL 语句,为多行插入做准备。对于一个符合 MRI 条件的事务来说,Q APPLY 会动态地准备插入语句,对于已经制备好的语句可以被后续的 SQL 操作复用,这大大提高了复制准备过程的效率。值得注意的是,每一次 MRI 操作也具有原子性,要么全部执行,要么全部不执行。如果在插入操作中,有任何一行插入操作失败,那些所有对数据库改变的 SQL 语句将会回滚,其中包括这个事务中已经执行成功的操作。
Q APPLY 在复制中会动态地分配空间,一旦 Q APPLY 获悉内存分配失败,它就会首先容错,然后切换到单行插入模式。接着继续使用单排插入模式去执行插入操作。如果它仍内存分配失败,Q APPLY 将告知用户错误,这与现有的 Q REP 行为处理一致。
最后 Q APPLY 执行多行插入并处理返回的错误。对于符合 MRI 的连续插入 INSERT SQL 的每一行,Q APPLY 都将会把列数据复制到相应的连续存储空间,然后执行语句。当返回值 SQLCODE 等于 0,证明所有的行插入成功。如果 SQLCODE 返回负数值(目前 Q APPLY 将不处理 SQLCODE 返回正数值),Q APPLY 将切换到单行插入模式去处理所有的已经完成的插入操作,以及最后一个引起的错误的插入操作。例如下图 3 所示,对同一个表 T1 插入数据,当第 K+2 行出现错误,将会以单行插入的方式处理已经完成的所有操作,下一个多行插入将重新定位,从这个事务中剩余的未插入行重新开始。在一个事务中,如果一个还未插入的行的总数量大于零,则继续重复上述操作。
图 3. 错误处理
MULTI_ROW_INSERT,指示 Q APPLY 程序是否使用多行插入 SQL。它是是否使用 MRI 新特性的标志。
表 1. MULTI_ROW_INSERT
列名 | 数据类型 | 可否为空 | 描述 |
---|---|---|---|
MULTI_ROW_INSERT | CHAR(1) | 不可为空 | N (默认值) Q APPLY 程序不使用多行插入,每个插入 SQL 语句将单独执行。 Y 对同一个表的连续插入语句,Q APPLY 程序使用多行插入 SQL 语句。 |
MRI_MEMORY_LIMIT,只能在 IBMQREP_APPLYPARMS 表中 MULTI_ROW_INSERT = Y 时应用。Q APPLY 代理使用 MRI_MEMORY_LIMIT 的值大小作为每个多行插入输入缓冲区。默认值是 1024KB(最大值)。这个输入缓冲区的大小决定了在一个 SQL 操作中可以有多少行。此参数将不再是一个隐藏的命令行参数,而是作为控制表可以修改的列值,以便用户在调整内存控制时使用 Q APPLY。
表 2. MRI_MEMORY_LIMIT
列名 | 数据类型 | 可否为空 | 描述 |
---|---|---|---|
MRI_MEMORY_LIMIT | INTEGER | 不可为空 | 默认值为 1024,值的有效范围是任何非负整数。 |
一下几列在验证 Q APPLY 是否正确复制有比较关键的意义:
表 3. MRI_MEMORY_LIMIT
列名 | 数据类型 | 可否为空 | 描述 |
---|---|---|---|
NUM_MRI_STMTS_EXECUTED | INTEGER | 可为空 | 在 monitor interval 间隔期间,Q APPLY 代理使用多行插入提交的事务的总次数。 |
ROWS_PROCESSED_MRI | INTEGER | 可为空 | 表示在 monitor interval 间隔期间,使用多行插入特性,来自接受队列和 APPLY 的被处理但未被提交到目标端的行的总数。这个列的值是 rows_processed 的一个子集。 |
CURRENT_MEMORY_STMT_CACHE | INTEGER | 可为空 | 内存总量以 byte 为单位,用于 Q APPLY 代理执行插入/删除/更新 SQL 语句。 |
STMTS_PREPARED | INTEGER | 可为空 | 指实际的准备好的语句的数目,其取决于定期的工作量以及需要准备 MRI statement 的频率。 |
在 Q APPLY 启动时使用,该 MULTI_ROW_INSERT 参数是一个 flag 标示,它指示 Q APPLY 程序是否使用多行插入 SQL 语句,其默认值是 Yes,如下所示。
清单 1. 调用 QAPPLY
>>-asnqapp--apply_server=db_name -+---------------------+--> '-apply_schema=schema-' >-+-------------------------+-> | .-y-. | '-multi_row_insert=-+-n-+-'
只要事务包含相同 sub ID,而且对用一个表进行插入操作,就符合 MRI 多行插入的要求。例如,有两个表 T1 和 T2,每个表都有两列,分别是 C1 和 C2,它们都是 int 类型。事务中有这样的一系列语句:
清单 2. workload
1. Insert into T1(1,1); 2. Update T1 set c2=2; 3. Insert into T2(1,1); 4. Insert into T2(10,20); 5. Insert into T1(4,19); 6. Insert into T1(3,7); 7. Insert into T1(12,6); 8. Commit;
对于上面的事务例子来说,第 3、4 语句可以对表 T2 应用 MRI 把数据插入到数据库中,第 5、6、7 语句可以对表 T1 应用 MRI 插入数据。
首先设置前提为控制表中 AGENT_STMT_CACHE_SZ = 50,意味如果 STMTS_PREPARED 的值大于 50 时,将会复用内存。这时进行如下操作:
期望的正确结果是:
回页首
回页首
IBM Q Replication 产品一直遵循着不断满足客户需求的宗旨,在 Q Replication V10.2.1 版本中,新特性 MRI 将多行插入合并成一个行集,把对数据库的多次访问合并成一个操作,明显地减少了插入数据库所需时间,保持着数据复制效率近实时特性,解决了大负载量数据复制高性能的需求。在性能上的卓越表现,也决定着 MRI 新特性在数据复制中的广泛应用。