频繁执行结构相同但参数不同的 SQL 语句时,可通过批量优化手段提升执行效率,这类优化通常涉及客户端与 OBServer 服务端两侧。在客户端,可通过配置 JDBC 参数将多条 SQL 批量发送至服务端;而在服务端,则可对批量 SQL 进行语句改写,生成适用于批量场景的执行计划。然而实际使用中,常常出现多条 INSERT 语句无法启用 BATCH 优化,进而导致执行性能不佳的问题。其中,参数中包含 NULL 或表达式结果为 NULL 是导致无法启用批量优化的常见原因之一。 针对含 NULL 参数的 SQL 语句难以命中批量优化的问题,本文将分析其生效的前提条件,并评估实际的优化效果与计划命中情况。
详细说明
Multi insert 走上批量处理优化的前提条件
Oracle 模式配置
useArrayBinding: 默认值为 False。此参数控制 JDBC 是否使用
Array Binding协议,该协议仅在PreparedStatement (PS)协议下生效。启用后,执行executeBatch()时,JDBC 客户端会将批量参数以数组形式打包发送至 OBServer 端,以提升效率。useServerPrepStmts: 默认值为 False。此参数用于开启服务端预编译。启用此参数后,SQL 会在服务器端通过
PrepareStatement执行。只有同时设置此参数和useArrayBinding,才能使用Array Binding协议。
在 Oracle 模式下,推荐将以上两个参数均设置为 True。此外,由于 rewriteBatchedStatements 与 useServerPrepStmts 的功能是互斥的,为避免冲突,请确保在 Oracle 模式下不要配置 allowMultiQueries 和 rewriteBatchedStatements 参数。
驱动版本要求
建议升级至 oceanbase-client-2.4.15 版本。 旧版本存在 NULL 类型兼容性问题,无法支持此场景下的 Array Binding 优化。
OceanBase 内核版本要求
针对 OceanBase 数据库 V4.2.5 BP5 版本,在 Python + OBCI 写入场景下,其行为与原生 OceanBase 存在显著差异。在满足前述条件并启用 Array Binding 时,NULL 值的处理规则如下: 普通 NULL(非表达式):在 Oracle 模式下可以正常启用 BATCH 优化。此场景对 NULL 值的个数、出现位置乃至参数全为 NULL 的情况均无限制。 表达式中的 NULL:目前不支持 BATCH 优化。
批量处理的 SQL 执行能否命中计划?
对于 Array Binding 中包含 NULL 表达式的场景,能否命中计划首先取决于 BATCH 优化是否生效,并进一步受到 NULL 表达式个数和位置的影响。
Oracle 模式,不建议使用 allowMultiQueries
在 Oracle 模式下,强烈不建议开启 allowMultiQueries 参数(PS模式)。启用后,JDBC 会将多条独立语句拼接成单个长 SQL。若拼接后的 SQL 长度过大,还需调整 maxBatchTotalParamsNum 参数值。 在 PS 模式下执行批量 INSERT 时,若参数中包含表达式 NULL 或 NULL 值的组合方式不同,每种组合都会生成独立的 plan_id。这不仅受 NULL 的个数和位置影响,还极易因计划版本过多而触发单条 SQL 的 200 个执行计划上限。
适用版本
OceanBase 数据库 V4.x 版本。