当前位置: 首页 > news >正文

33-Oracle Parallel 并行处理的选择和实践

小伙伴们是不是偶尔会遇见超大的表,几百万、上千万行的数据,查询或是导出各种卡顿,服务器现在都是十核上百核心了,内存也轻轻松松到几十g上百g了。如果使用并行来用好机器的实力,跑起来,快起来。使用并行查询将执行时间大大缩短,在什么场景上可以使用呢,有啥要规避的。

一、Parallel并行

​1. 技术本质​

通过任务分解-并行执行-结果合并流程(QC进程+PX Slaves架构),将单进程任务拆分为多进程并发处理,实现近乎线性的性能扩展

2. 适用场景

类型

​举例​

​性能提升依据

OLAP查询​

亿级表全表扫描、多表JOIN

并行扫描使多线程查询耗时降至串行

​批量DML​

千万级数据UPDATE/INSERT

PDML通过并行写入减少事务提交次数

对象维护​

大表在线重定义、索引创建

并行建索引速度提升

​数据迁移​

Data Pump导出TB级数据

PARALLEL参数加速RAC集群资源利用

规避的场景​:

高频OLTP事务(行级锁冲突)、含触发器依赖操作、资源受限(CPU/I/O 瓶颈)系统开了会更卡。

二、实践脚本

​1. 创建测试表(千万行数据)​​真实的医疗和工业生产,大量的这样的表。

 

ALTER SESSION ENABLE PARALLEL DML;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 32;
ALTER TABLE target_table NOLOGGING;  -- 减少Redo日志
ALTER INDEX idx_parallel REBUILD PARALLEL 32;  -- 完成后并行重建索引-- 创建大表(2千万行)19c环境,sql中的connect by功能太香了速度快,
--然而1亿条的时候直接ORA-300009,32C/128G,SGA=64G
-- 启用并行 DML 并设置并行度(推荐 DOP = CPU 核心数 × 0.75)
ALTER SESSION ENABLE PARALLEL DML;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 24;
ALTER SESSION FORCE PARALLEL DDL PARALLEL 24;-- 创建表(NOLOGGING + PARALLEL + 直接路径插入)
CREATE TABLE sales_data 
PARALLEL 32 
NOLOGGING 
AS 
SELECT /*+ APPEND PARALLEL(24) */ROWNUM AS id,TRUNC(DBMS_RANDOM.VALUE(1,1000)) AS product_id,TRUNC(SYSDATE - DBMS_RANDOM.VALUE(1,3650)) AS sale_date,ROUND(DBMS_RANDOM.VALUE(10,5000), 2) AS amount
FROM DUAL 
CONNECT BY LEVEL <= 20000000;-- 恢复表属性(避免后续操作继承并行设置)
ALTER TABLE sales_data NOPARALLEL;
ALTER TABLE sales_data LOGGING;
--
----实际运行
[oracle@test19:/home/oracle]# sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on 星期六 6月 14 14:29:23 2025
Version 19.3.0.0.0Copyright (c) 1982, 2019, Oracle.  All rights reserved.
连接到:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0SYS@test19> show pdbs;CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------2 PDB$SEED                       READ ONLY  NO3 PDBRS6                         READ WRITE NO
SYS@test19> alter session set container=PDBRS6;
----

创建时候机器负载

2. 场景1聚合统计:并行查询 vs 串行查询 
--比较执行时间,十几倍的提升
-- 串行查询(全表扫描)
SET TIMING ON
SELECT /*+ NO_PARALLEL */ product_id, SUM(amount) 
FROM sales_data 
GROUP BY product_id; 
-- 执行时间:已用时间:  00: 00: 02.98-- 并行查询(DOP=8)
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 8;
SELECT /*+ PARALLEL(sales_data, 8) */ product_id, SUM(amount) 
FROM sales_data 
GROUP BY product_id;
-- 执行时间:已用时间:  00: 00: 00.45
3. 场景2批量更新:并行DML vs 串行DML 
-- 串行更新
UPDATE /*+ NO_PARALLEL */ sales_data 
SET amount = amount * 1.1 
WHERE product_id BETWEEN 100 AND 200; 
--已更新 2022843 行。
--已用时间:  00: 01: 46.64-- 并行DML(需显式启用)
ALTER SESSION ENABLE PARALLEL DML;UPDATE /*+ PARALLEL(sales_data, 8) */ sales_data 
SET amount = amount * 1.1 
WHERE product_id BETWEEN 100 AND 200;
COMMIT;  -- 必须提交释放资源
已更新 2022843 行。
已用时间:  00: 00: 17.97
COMMIT
提交完成。
已用时间:  00: 00: 00.11
4. 场景3索引创建:并行DDL 
-- 串行创建索引
CREATE INDEX idx_serial ON sales_data(product_id);
-- 索引已创建。
--已用时间:  00: 00: 25.31
-- 并行创建索引(DOP=12)
SYS@test19> DROP INDEX idx_serial;
索引已删除。
已用时间:  00: 00: 00.17
CREATE INDEX idx_parallel ON sales_data(product_id) PARALLEL 12;
SYS@test19> CREATE INDEX idx_parallel ON sales_data(product_id) PARALLEL 12;
索引已创建。
-- 已用时间:  00: 00: 02.37 
-- 关闭并行属性
ALTER INDEX idx_parallel NOPARALLEL;
索引已更改。
已用时间:  00: 00: 00.02

三、最佳实践与避坑指南

​1. 并行度计算公式​

DOP=(CPU C​ores×parallel t​hreads p​erc​ pu)×0.75−−预留25%

-- 查看系统参数  
SHOW PARAMETER cpu_count;              -- CPU核心数
SYS@test19> SHOW PARAMETER cpu_count;
NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
cpu_count                            integer                           32SHOW PARAMETER parallel_threads_per_cpu; --虚拟CPU 
SYS@test19> SHOW PARAMETER parallel_threads_per_cpu
NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
parallel_threads_per_cpu             integer                           1
2. 对应配置 
-- 限制全局并行进程数(防资源耗尽)  
ALTER SYSTEM SET parallel_max_servers = 64;  
-- 启用自适应并行(Oracle 11g+)  
ALTER SESSION SET parallel_degree_policy = AUTO;  
SYS@test19> ALTER SYSTEM SET parallel_max_servers = 64;
系统已更改。
已用时间:  00: 00: 00.01
SYS@test19> ALTER SESSION SET parallel_degree_policy = AUTO;
会话已更改。
已用时间:  00: 00: 00.00
4. 常见问题
  • 1​:并行更新后查询报错 ORA-12838​原因​:未提交事务导致后续会话无法读取被修改的表。​解决​:执行 COMMIT 后重试。
  • 2​:并行DDL引发 ORA-00600 错误​原因​:parallel_execution_message_size 参数过小。
ALTER SYSTEM SET parallel_execution_message_size=8192 SCOPE=SPFILE;  
SHUTDOWN IMMEDIATE;  
STARTUP;
--
SYS@test19> show parameter parallel_execution_message_size;NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
parallel_execution_message_size      integer                           16384
 3​:生效​验证步骤​,并行查询:
-- 生成执行计划(不实际执行SQL)
EXPLAIN PLAN FOR 
SELECT /*+ PARALLEL(sales_data, 8) */ product_id, SUM(amount) 
FROM sales_data 
GROUP BY product_id;
-- 检查执行计划中的并行标识
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(FORMAT=>'ALL'));
SYS@test19> show parameter parallel_execution_message_size;NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
parallel_execution_message_size      integer                           16384
EXPLAIN PLAN FOR
SELECT /*+ PARALLEL(sales_data, 8) */product_id, SUM(amount)
FROM sales_data5  GROUP BY product_id;已解释。已用时间:  00: 00: 00.04
SYS@test19> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(FORMAT=>'ALL'));PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3011834688--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |            |    20M|   503M|  3005   (4)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR          |            |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001   |    20M|   503M|  3005   (4)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY         |            |    20M|   503M|  3005   (4)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE           |            |    20M|   503M|  3005   (4)| 00:00:01 |  Q1,01 | PCWP |            |
|   5 |      PX SEND HASH        | :TQ10000   |    20M|   503M|  3005   (4)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       HASH GROUP BY      |            |    20M|   503M|  3005   (4)| 00:00:01 |  Q1,00 | PCWP |            |
|   7 |        PX BLOCK ITERATOR |            |    20M|   503M|  2914   (1)| 00:00:01 |  Q1,00 | PCWC |            |
|   8 |         TABLE ACCESS FULL| SALES_DATA |    20M|   503M|  2914   (1)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------1 - SEL$18 - SEL$1 / SALES_DATA@SEL$1Column Projection Information (identified by operation id):
-----------------------------------------------------------1 - "PRODUCT_ID"[NUMBER,22], SUM()[22]2 - (#keys=0) "PRODUCT_ID"[NUMBER,22], SUM()[22]3 - (#keys=1; rowset=256) "PRODUCT_ID"[NUMBER,22], SUM()[22]4 - (rowset=256) "PRODUCT_ID"[NUMBER,22], SYS_OP_MSR()[25]5 - (#keys=1) "PRODUCT_ID"[NUMBER,22], SYS_OP_MSR()[25]6 - (#keys=1; rowset=256) "PRODUCT_ID"[NUMBER,22], SYS_OP_MSR()[25]7 - (rowset=256) "PRODUCT_ID"[NUMBER,22], "AMOUNT"[NUMBER,22]8 - (rowset=256) "PRODUCT_ID"[NUMBER,22], "AMOUNT"[NUMBER,22]Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------8 -  SEL$1 / SALES_DATA@SEL$1-  PARALLEL(sales_data, 8)Note
------ dynamic statistics used: dynamic sampling (level=4)- Degree of Parallelism is 8 because of hint已选择 45 行。已用时间:  00: 00: 00.24

“数据量越大,并行收益越高;资源越充足,加速比越接近线性”​​,

同时这是一把双刃剑,避免滥用并行!优先通过索引优化、SQL 调优解决性能问题。

仅在硬件资源充足且数据量巨大时启用并行,否则可能拖垮系统

相关文章:

  • 31-Oracle 23 ai-Unrestrict Parallel DML(无限制并行DML)
  • SAP复制一个自定义移动类型
  • 篇章七 论坛系统——业务开发——前端
  • Python 中的 `lru_cache` 详解
  • 掌握应用分层:高内聚低耦合的艺术
  • Python with 关键字
  • 【FineDance】ModuleNotFoundError: No module named ‘pytorch3d‘
  • 数据目录:企业数据管理的核心引擎与最佳实践
  • Linux02
  • Linux Docker的环境配置与简单使用
  • 【Day48】
  • Docker 在尝试连接 Docker Hub 时遇到网络问题(超时)
  • 27 - ASPP模块
  • TI 毫米波雷达走读系列—— 3DFFT及测角
  • 疫菌QBD案例
  • Spring-rabbit重试消费源码分析
  • 低温对MOSFET的影响
  • SpringBoot打包运行原理和加载机制原理
  • 篇章六 论坛系统——业务开发——实现业务功能
  • JUC核心解析系列(四)——同步工具类 (Synchronizers)深度解析
  • 免费装修设计app/专业黑帽seo推广
  • 上海 网站平台开发/网站关键词推广优化
  • 确保网站地址没有做301跳转/百度域名注册查询
  • 移动商城网站开发/2022最新免费的推广引流软件
  • 虞城网站建设/搜索引擎优化指南
  • 江苏专业做网站的公司有哪些/微信推广引流加精准客户