---
title: "并行执行入门实践 - OceanBase 数据库 V4.3.2 | OceanBase 文档中心"
description: 并行执行入门实践 并行执行是一个深度且复杂的主题，需要经过一定的学习阶段，方能准确理解并发操作的机制，将并行执行的能力发挥到更大。为了使初学者能够迅速掌握并行执行的要点，在 OceanBase 数据库 V3.1 及以上版本中，我们提供了一个入门实践的指南。尽管本文中提供的参数不是最优选择，但可以有效地避免大多数不良情…
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.3.2

# 并行执行入门实践

更新时间：2025-08-01 16:12:12

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.3.2/zh-CN/700.reference/1000.performance-tuning-guide/500.sql-optimization/350.parallel-execution/700.quickstart-of-parallel-execution.md)  

并行执行是一个深度且复杂的主题，需要经过一定的学习阶段，方能准确理解并发操作的机制，将并行执行的能力发挥到更大。为了使初学者能够迅速掌握并行执行的要点，在 OceanBase 数据库 V3.1 及以上版本中，我们提供了一个入门实践的指南。尽管本文中提供的参数不是最优选择，但可以有效地避免大多数不良情况，使初学者能够更轻松地应用并行执行的功能。

## 初始化环境

在 AP 租户下设置：

```sql
/* MySQL */
SET GLOBAL parallel_servers_target = MIN_CPU * 20;

/* Oracle */
ALTER SYSTEM SET parallel_servers_target = MIN_CPU * 20;

```

其中 `MIN_CPU` 表示 CPU 规格的下限，关于设置每个 Server 上并行查询排队条件的详细信息，参见 [parallel_servers_target](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001052719)。

## 统计信息搜集

V3.x 版本的统计信息搜集跟合并绑定，所以在导入数据之后，需要发起一轮合并才能保证统计信息的搜集。

V4.x 版本在导入数据之后，可以直接调用 DBMS 统计信息包来搜集统计信息。

更多关于统计信息，请参考 [统计信息概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053594)。

## 设置 Hint

每条 SQL 的并行度（DOP），最大不要超过物理 CPU 数量的 1.5 倍。 一般来说，如果没有多个 SQL 并发执行，单条 SQL 的并行度可以设置为 CPU 数。例如，系统的物理 CPU 数为 32，那么 Hint 就设置为 `/*+ PARALLEL(32) */`。

## 性能调优

1. 通过 `top -H` 查看租户 CPU 使用情况。
 2. 单条 SQL 性能不符合预期，请使用 `sql_plan_monitor` 获取性能报告。

```sql
-- open_dt 表示算子从 Open 到 Close 的时间间隔
-- row_dt 表示算子从吐出第一行，到吐出 OB_ITER_END 的时间间隔
-- 如果值为 NULL，表示没有吐出过第一行或者没有吐出过 OB_ITER_END

-- 请给慢 SQL 增加一个 Hint： /*+ monitor */
-- 执行增加 Hint 后的慢 SQL，可以得到 Trace_id，替换下面的 Yxxxxxxxxx，执行下面的 SQL

-- MySQL 租户：
-- 汇总：
SELECT op_id, op, rows, rescan, threads, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt,  open_time, close_time,  first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, concat(lpad('', plan_depth, ' '), plan_operation) op, sum(output_rows) rows, sum(STARTS) rescan, min(first_refresh_time) open_time, max(last_refresh_time) close_time, min(first_change_time) first_row_time, max(last_change_time) last_row_eof_time, count(1) threads from oceanbase.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' group by  plan_line_id, plan_operation order by plan_line_id
) a;

-- 明细
SELECT op_id, thread, op, rows, rescan, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time  FROM
(
select plan_line_id op_id, PROCESS_NAME thread, concat(lpad('', plan_depth, ' '), plan_operation) op, output_rows rows, STARTS rescan, first_refresh_time open_time, last_refresh_time close_time, first_change_time first_row_time, last_change_time last_row_eof_time from oceanbase.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' order by plan_line_id, PROCESS_NAME
) a;

-- Oracle 租户：
--说明：open_dt 表示算子从 Open 到 Close 的时间间隔
--说明：row_dt 表示算子从吐出第一行，到吐出 OB_ITER_END 的时间间隔
--说明：如果值为 NULL，表示没有突出过第一行或者没有突出过 OB_ITER_END

-- 汇总
SELECT op_id, op, output_rows, rescan,threads ,(close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt,  open_time, close_time,  first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, concat(lpad(' ', max(plan_depth), ' '), plan_operation) op, sum(output_rows) output_rows, sum(STARTS) rescan, min(first_refresh_time) open_time, max(last_refresh_time) close_time, min(first_change_time) first_row_time, max(last_change_time) last_row_eof_time, count(1) threads from sys.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' group by  plan_line_id, plan_operation,plan_depth order by plan_line_id
) a;

-- 明细
SELECT op_id, thread, op, output_rows, rescan, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, PROCESS_NAME thread, concat(lpad(' ', plan_depth, ' '), plan_operation) op, output_rows, STARTS rescan, first_refresh_time open_time, last_refresh_time close_time, first_change_time first_row_time, last_change_time last_row_eof_time  from sys.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' order by plan_line_id, process_name
) a;

```

## 常见问题

1. Query 查询性能不符合预期，CPU 没用满？ 请执行 `show variables like 'parallel_servers_target` 确认 target 值不小于 `MIN_CPU` * 20。
 2. PDML 性能不符合预期？

   请使用 `explain extended` 解释 PDML，确认计划走了 PDML。如果没有走 PDML，计划最底部的 Note 字段会说明原因。一般是因为被修改的表包含了 trigger、外键、`local unique index` 等原因。

   如果出现 `DISTRIBUTED INSERT`，`DISTRIBUTED UPDATE`，`DISTRIBUTED DELETE` 等字样，就说明没有走 PDML。
 3. PDML 超时，内部日志显示出现 `-4138 OB_SNAPSHOT_DISCARDED` 报错？

   请调大 `undo_retention` 参数，使其不小于 PDML 的最大执行时间。它的默认值只有 30 分钟，一旦 PDML 执行时间超过 30 分钟，就可能遇到这个问题，导致执行终止，重试，直到超时。

   Oceanbase V4.1 版本及以上已经无 PDML 超时问题发生，无需手动设置 `undo_retention`。
 4. 业务不能做任何修改，如何让业务 SQL 并行起来？

   OBProxy 允许用户在 Web 界面上修改连接配置，开启并行。例如，在读写分离连接上，将全部 SQL 的并行度设置为 2。

 上一篇 下一篇 ![有帮助](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) 咨询热线
