---
title: OceanBase 的 Batch 执行-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 OceanBase 的 Batch 执行相关的常见问题和使用技巧，帮助您快速解决 OceanBase 的 Batch 执行的难题。
---
切换语言

- 简体中文
- English

划线反馈

# OceanBase 的 Batch 执行

更新时间：2025-03-02 03:26

适用版本： V1.4.x、V2.1.x、V2.2.x、V3.1.x、V3.2.x 内容类型：FAQ  

## OceanBase 的 Batch 执行是什么？

当使用 JDBC 和 OceanBase 进行交互时，可以把多次请求放进一个组，从而进行一次网络传输完成多次请求，这被称为 Batch 执行，通常也被称为批处理。

## 为什么要使用 Batch 执行？

有时候会因为数据的一致性而使用 Batch 执行，但更多时候，使用 Batch 执行最大的好处是可以提升性能，这体现在几个方面：

- Batch 执行可以减少和数据库的交互次数。
 - Batch 语句会被改写以提高性能。
 - OceanBase 在收到 Batch 执行时可以做一些优化工作，进一步提升性能。

## JDBC 中哪些 class/object 可以实现 Batch 执行？

无论使用 Statement 还是 PrepareStatement 都可以实现 Batch 执行。

## 使用 Batch 执行需要设置什么 JDBC 配置属性？

- 从功能上说，使用 Batch 执行必须要设置 `rewriteBatchedStatements=TRUE`。
 - 从实现和行为上说，useServerPrepStmts 会决定 Batch 执行的不同行为。
 - 从性能上说，cachePrepStmts，prepStmtCacheSize，prepStmtCacheSqlLimit，maxBatchTotalParamsNum 会对性能上有所帮助。

| 配置属性 | 默认值 | 说明 |
| --- | --- | --- |
| allowMultiQueries | FALSE | 决定一条语句中是否可以用 `;` 分割多个请求，Batch 执行并不依赖于这个属性，而仅仅依赖于 `rewriteBatchedStatements`。   #### 注意    - 如果 JDBC 版本小于等于 1.1.9，则 `allowMultiQueries` 必须开启 update 语句才会用；拼接，否则将报错：`Not supported feature or function`。 - 如果 JDBC 版本大于等于 2.2.6，则 `allowMultiQueries` 是否开启是没有影响的。 |
| rewriteBatchedStatements | FALSE | 决定 Batch 执行中是否会重写 INSERT 语句。对于 PrepareStatement 对象，会使用多个 VALUES 来拼接；对于 Statement 对象，会使用分号来拼接多个 INSERT 语句。 |
| useServerPrepStmts | FALSE | 决定是否使用 Server 端的 Prepared 语句，仅对 PrepareStatement 对象有效。   - TRUE 表示使用 Server 端的 Prepared 语句，这需要在 OBServer 端开启 `_ob_enable_prepared_statement`，同时意味着使用二进制协议进行通讯。 - FALSE 表示使用 Client 端的 Prepared 语句，同时意味着使用文本协议进行通讯。    #### 注意    如果设置了 `useCursorFetch=true`，则 useServerPrepStmts 会被强制设置为 true。 |
| cachePrepStmts | FALSE/TRUE | 决定 JDBC driver 是否缓存 Prepared 语句，针对 Client 端的 Prepared 语句和 server 端的 Prepared 语句，缓存的内容稍有不同。   #### 注意    - 在 OceanBase JDBC V1.x 版本中默认是 FALSE。 - 在 OceanBase JDBC V2.x 版本中默认是 TRUE。 |
| prepStmtCacheSize | 25/250 | 如果开启了 cachePrepStmts，决定了可以缓存多少条 prepared statements。   #### 注意    - 在 OceanBase JDBC V1.x 版本中默认是 25。 - 在 OceanBase JDBC V2.x 版本中默认是 250。 |
| prepStmtCacheSqlLimit | 256/2048 | 如果开启了 cachePrepStmts，决定了可以缓存最大的 SQL 是多大。   #### 注意    - 在 OceanBase JDBC V1.x 版本中默认是 256。 - 在 OceanBase JDBC V2.x 版本中默认是 2048。 |
| maxBatchTotalParamsNum | 30000 | 当使用 executeBatch，决定了最大可以拼接多少个参数。   #### 注意    - 该参数仅在 OceanBase JDBC V2.2.7 及以后才存在。 |

## 哪些 OceanBase 的配置项/变量和 Batch 执行有关？

如下配置项和 Batch 执行有关系

| 参数 | 默认值 | 范围 | 生效方式 | 含义 |
| --- | --- | --- | --- | --- |
| ob_enable_batched_multi_statement | FALSE | 租户 | 动态 | 用于设置是否启用批处理多条语句的功能。开启这个参数同时也意味着：在 Batch 执行场景下，当 Client/Server 使用文本协议进行通许时，OceanBase 会对格式一致的多条 UPDATE 语句当成一条语句进行解析，并根据对应的参数和数据分布，生成 batch physical plan。 |
| _ob_enable_prepared_statement | FALSE | 集群 | 动态 | 表示是否可以使用 server 端的 Prepared 语句 |
| _enable_static_typing_engine | TRUE | 集群 | 动态 | 指定是否使用新的 SQL 引擎。新老的 SQL 引擎对于是否能处理 Batch UPDATE 有差别，老引擎只能处理包含全部主键的 Batch UPDATE，新引擎虽然能处理不包含全部主键的 Batch UPDATE，但需要在较新分支的 OceanBase V3.2 版本才能有这个能力。 |

| 变量 | 默认值 | 级别 | 含义 |
| --- | --- | --- | --- |
| _enable_dist_data_access_service | TRUE | session/global | 打开或者关闭 SQL 以 DAS 的方式执行，在 OceanBase V3.2 版本后的新 SQL 引擎中，如需要获得 Batch UPDATE 的优化能力，需要打开这个变量。 |

## Statement 和 PrepareStatement 在行为和使用方法上有什么不同？

- 使用 Statement 对象

  ```shell
  conn = DriverManager.getConnection(obUrl);
  conn.setAutoCommit(false);
  Statement stmt = conn.createStatement();
  String SQL = "INSERT INTO test1 (c1, c2) VALUES (1, 'test11')";
  stmt.addBatch(SQL);
  String SQL = "INSERT INTO test1 (c1, c2) VALUES (2, 'test12')";
  stmt.addBatch(SQL);
  String SQL = "INSERT INTO test1 (c1, c2) VALUES (3, 'test13')";
  stmt.addBatch(SQL);
  int[] count = stmt.executeBatch();
  stmt.clearBatch();
  conn.commit();

  ```
 - 使用 PrepareStatement 对象

  ```shell
  conn = DriverManager.getConnection(obUrl);
  conn.setAutoCommit(false);
  String SQL = "INSERT INTO TEST1 (C1, C2) VALUES (?, ?)";
  PreparedStatemen pstmt = conn.prepareStatement(SQL);
  int rowCount = 5, batchCount = 10;
  for (int k=1; k<=batchCount; k++) {
      for (int i=1; i<=rowCount; i++) {
          pstmt.setInt(1, (k*100+i));
          pstmt.setString(2, "test value");
          pstmt.addBatch();
      }
      int[] count = pstmt.executeBatch();
      pstmt.clearBatch();
  }
  conn.commit();
  pstmt.close();

  ```

下表列出使用 PrepareStatement 和 Statement 对象时，Batch 执行的不同行为，前提需要 `rewriteBatchedStatements=TRUE` 。

- PrepareStatement：

  | useServerPrepStmts | INSERT | UPDATE | 备注 |
  | --- | --- | --- | --- |
  | TRUE | 多条 INSERT 语句的 VALUES 会以多个 `?` 的形式拼接在一条 INSERT 语句的多个 VALUES 中，形如：INSERT INTO TEST1 VALUES (?), (?),...,(?) | 多条单独的 UPDATE 语句，其中的变量用 `?` 替代 | 场景 1 |
  | FALSE | 多条 INSERT 语句的 VALUES 会以多个具体值的形式拼接在一条 INSERT 语句的多个 VALUES 中，形如：INSERT INTO TEST1 VALUES (1), (2),...,(10) | 多条单独的 UPDATE 语句用分号拼接在一起 | 场景 2 |
 - Statement：

  | useServerPrepStmts | INSERT | UPDATE | 备注 |
  | --- | --- | --- | --- |
  | TRUE | 多条单独的 INSERT 语句用分号拼接在一起 | 多条单独的 UPDATE 语句用分号拼接在一起 | 场景 3 |
  | FALSE | 多条单独的 INSERT 语句用分号拼接在一起 | 多条单独的 UPDATE 语句用分号拼接在一起 | 场景 4 |

## OceanBase 的 Batch 执行有哪些类型？分别对请求的优化处理有哪些？

从语句角度看，OceanBase 的 Batch 执行针对 INSERT，UPDATE 和 DELETE 的处理是不同的，这从上表也可以看出，具体如下：

### INSERT

在场景 1 中，OceanBase 服务器端会收到一次 INSERT 语句的 `COM_STMT_PREPARE` 请求（request_type=5）和 一次 INSERT 语句的 `COM_STMT_EXECUTE` 请求（request_type=6），从优化的角度看，有如下好处：

- 只需要发生两次通讯就完成了 INSERT 语句的 Batch 执行。
 - PrepareStatement 天然的属性可以减少编译时间。
 - 假设后续有更多的 executeBatch，且设置了合理的 cachePrepStmts 及相关参数，可以减少 prepare 请求（request_type=5）的次数，而只需要执行 execute 请求（request_type=6）。

在场景 2 中，OceanBase 服务器端会收到一次 INSERT 语句的 `COM_QUERY` 请求（request_type=2），从优化的角度看，有如下好处：

- 只需要发生一次通讯就完成了 INSERT 语句的 Batch 执行。

在场景 3 和 4 中，OceanBase 服务器端会收到一个由多条 INSERT 语句用分号拼接在一起的请求，并依次执行，所以也具有如下好处：

### UPDATE

如果没有开启 `ob_enable_batched_multi_statement`，场景 1/2/3/4 的 UPDATE Batch 执行在 OceanBase server 端都会被依次执行，不会有特别的优化。

如果开启了 `ob_enable_batched_multi_statement`，那么对于场景 2/3/4 的 UPDATE Batch 执行，OceanBase server 端会对格式一致的多条 UPDATE 语句当成一条语句进行解析，并根据对应的参数和数据分布，生成 batch physical plan，这可以有效的提升 Batch UPDATE 执行的效率。但在使用这个功能上有几个注意事项：

- 在 OceanBase V3.1 版本中，仅当 UPDATE 的谓语中包含全部的主键时才能被优化；在 OceanBase V3.2 版本中，可以没有这个限制，但需要确保打开 `_enable_dist_data_access_service` 变量并启用新 SQL 引擎 `_enable_static_typing_engine=TRUE`。
 - 同一批次的 UPDATE 中不能有相同的行。
 - 需要开启显式事务。

### DELETE

当前版本对于 Batch DELETE，都是依次执行。

## 如何在不同的场景下选择不同的配置？

如果可能，尽量选择较新版本的 oceanbase-client jar 包，如上表所示，1.x 和 2.x 的 jar 包行为有些许不同，1.1.9 版本的 jar 包在 Oracle 租户下还有些缺陷。

### Batch INSERT

场景 1/2 能更有效的发挥 Batch 执行的性能，推荐配置如下：

场景 1:

- JDBC 对象：

  PrepareStatement 对象
 - Server 端参数：

  _ob_enable_prepared_statement=TRUE
 - JDBC 配置属性：

  rewriteBatchedStatements=TRUE

  useServerPrepStmts=TRUE

  cachePrepStmts=TRUE

  prepStmtCacheSize=<根据实际情况>

  prepStmtCacheSqlLimit=<根据实际情况>

  maxBatchTotalParamsNum=<根据实际情况>

场景 2:

  PrepareStatement 对象
 - JDBC 配置属性：

  useServerPrepStmts=FALSE

### Batch UPDATE

场景 2/3/4 使用了文本协议进行通讯，因此都能利用到多 UPDATE 语句批处理的功能，推荐配置如下：

场景 2：

  ob_enable_batched_multi_statement=TRUE

  _enable_static_typing_engine=TRUE（OceanBase V3.2 版本需要）
 - Server 端变量：

  _enable_dist_data_access_service=1（OceanBase V3.2 版本需要）
 - JDBC 配置属性：

  allowMultiQueries=TRUE（设置这个是为了避免 JDBC 驱动不同版本间的行为差异）

场景 3/4：

  Statement 对象
 - Server 端参数：

## 如何查看 OceanBase 的 Batch 执行是否生效？

关于查看 OceanBase 的 Batch 执行是否生效，可参考文档 [如何查看 OceanBase 的 Batch 执行是否生效](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002393953)。

## Batch 执行时，executeBatch 方法返回的值是多少？

executeBatch 方法被调用后，会返回一个整型数组 int []。对于 Batch INSERT 和 Batch UPDATE 来说：

- 如果在 OceanBase 端最终是依次执行的，那么这个数组会返回 Batch 中每一个 Operation 所修改的行数。
 - 如果在 OceanBase 端最终是作为一个整体执行的，比如 JDBC 驱动把多条 INSERT 语句改成了一个 INSERT 语句的多个 values（场景1/2）；又比如 UPDATE 语句作为一个 batch physical plan 被执行（场景2），那么这个数组的每个元素会返回 -2，表示执行成功但更新行数未知。

## 适用版本

OceanBase 数据库 V1.x、V2.x、V3.x 版本。

Previous

[Oracle 租户使用 rowid 做为条件进行重复更新数据，第二次没有更新到数据的原因和解决方法](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000003702363)

Next

[如何查看 OceanBase 的 Batch 执行是否生效](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002393953) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
