解析Oracle 19C中并行INSERT SELECT的工作原理

Oracle 19C中并行INSERT SELECT语句原理及进程分配机制解析

问题

insert /*+ parallel (a 16) append */ into a select /*+ parallel 16*/ * from b partition(p1); 语句在Oracle 19c中的执行原理,以及其是否会自动生成32个操作系统进程?

1. 问题简单理解

  • 执行原理: 该语句的执行采用了经典的生产者-消费者(Producer-Consumer)模型SELECT 部分作为"生产者",由一组并行执行服务器(Parallel Execution Servers)负责并行地从表 bp1 分区读取数据。INSERT 部分作为消费者,由另一组并行执行服务器负责接收数据并以直接路径(Direct-Path)方式并行地写入表 a。这两个操作的并行决策是相互独立的 。

  • 进程数量分析: 该语句不会简单地因为两个并行提示(parallel 16)相加而生成 16 + 16 = 32 个进程

2. SQL语句的核心原理剖析

给定的SQL语句 insert /*+ parallel (a 16) append */ into a select /*+ parallel 16*/ * from b partition(p1); 包含了多个Oracle性能优化的关键特性。要理解其工作原理,必须解构其各个组成部分。

2.1 并行DML (Parallel DML) 与 INSERT 操作

语句的 INSERT 部分包含了 /*+ parallel (a 16) */ 提示,这明确指示Oracle对目标表 a 的插入操作启用并行DML,并请求并行度(DOP)为16 。

  • 并行DML机制:Oracle将DML操作(在此为INSERT)分解为多个独立的子任务,分配给一组称为"并行执行服务器"(Parallel Execution Servers)的后台进程同时执行 。这些服务器本质上是独立的操作系统进程 。
  • 启用条件 :要使并行DML生效,除了使用Hint提示外,通常需要在会话级别显式启用该功能:ALTER SESSION ENABLE PARALLEL DML 。若未启用,parallel提示将被忽略。

2.2 直接路径插入 (Direct-Path Insert) 与 APPEND 提示

append 提示是与并行DML协同工作的关键。它将传统的、经过缓冲区缓存(Buffer Cache)的插入操作,转换为直接路径插入 。

  • 工作方式:数据直接写入数据文件,绕过了SGA中的Buffer Cache。这减少了对缓存的争用和逻辑I/O,极大地提升了大数据量加载的性能 。
  • 与并行的协同APPENDPARALLEL 结合使用是大数据仓库(DW)和ETL场景下的最佳实践,能够实现最高效的数据加载 。

2.3 并行查询 (Parallel Query) 与 SELECT 操作

语句的 SELECT 部分包含了 /*+ parallel 16 */ 提示。这个提示独立地作用于查询操作,指示Oracle使用16的并行度来扫描源数据------即表 bp1 分区 。

  • 工作方式 :查询协调器(Query Coordinator)会将对 bp1 分区的扫描任务分解成多个数据块范围(rowid ranges or block ranges),然后分配给16个并行执行服务器去同时读取。

2.4 核心架构:生产者-消费者模型

当并行 INSERT 和并行 SELECT 结合在一条语句中时,Oracle的并行执行引擎会采用一个高效的生产者-消费者模型

  1. 生产者 (Producers) :一组并行执行服务器(由 SELECT 部分的 parallel 16 提示请求)负责并行扫描表 b 的分区 p1。它们是数据的生产者。
  2. 消费者 (Consumers) :另一组并行执行服务器(由 INSERT 部分的 parallel(a 16) 提示请求)负责从生产者那里接收数据,并将其并行地、以直接路径方式写入表 a。它们是数据的消费者。

生产者(SELECT)和消费者(INSERT)共享同一组并行进程,而非独立的两组

Oracle采用动态角色切换机制(同一进程先后执行生产/消费任务)

实际进程数 = 并行度(DOP) + 少量协调进程(通常 ≤ DOP + 1)

"To execute a query in parallel, Oracle creates a set of producer-consumer servers. Each server alternates roles between fetching and processing data blocks."

"Parallel DML operations share the same set of slaves for scanning and inserting"

复制代码
SELECT sid, server_name FROM v$px_session 
WHERE qcsid = (SELECT sid FROM v$session WHERE sql_id='xxx');
ps -ef | grep "ora_p00" | wc -l  # 执行期间增量≈DOP

关键在于,这是一个单一SQL操作内部的两个阶段,而不是两个独立的SQL操作。Oracle优化器会生成一个统一的执行计划,其中包含两个并行的部分。因此,所请求的并行执行服务器数量与这个模型的实现方式密切相关,而并非简单的提示数值相加。一些资料明确指出,在这种模型下,实际需要的并行服务进程数量可能是指定DOP的两倍 。

3. 操作系统进程数量的深度分析

基于上述原理,讨论这条语句是否会自动生成32个操作系统进程。

3.1 协调者进程 (Coordinator Process) 的角色

除了执行任务的从属进程(slave processes),并行操作还有一个协调者进程

  • 协调者不是新增进程:协调者通常是发起该SQL语句的用户会话所对应的服务器进程(Server Process)。它不作为一个新生成的操作系统进程计入并行操作的开销,而是承担了协调和管理的角色:解析SQL、生成执行计划、分发任务给并行服务器、以及最后汇总结果 。因此,在计算新生成的进程数时,不应将协调者额外加1。

3.2 实际进程数量的决定性因素与限制

理论上需要32个进程,但在实际环境中,Oracle几乎不可能总是精确地按这个数字分配。实际生成的进程数是一个动态决策的结果,受到以下关键因素的制约:

  1. PARALLEL_MAX_SERVERS 参数 :这是整个Oracle实例(Instance)中允许存在的并行执行服务器进程总数的硬性上限 。如果当前系统中活动的并行进程数加上本次请求的32个进程,超过了此参数的设定值,Oracle将无法满足请求。它可能会降低实际的并行度,甚至将操作排队等待或降级为串行执行 。

  2. PARALLEL_SERVERS_TARGET 参数:这个参数在12c及以后版本中引入,定义了在SQL开始排队之前,实例允许运行的并行服务器进程的目标数量 。如果当前活动的进程数已经达到这个目标值,新的并行请求可能会被排队。

  3. 系统资源与负载:Oracle会实时评估CPU、内存和I/O的负载情况。如果系统资源紧张,即使配置参数允许,Oracle也可能会主动降低实际分配的并行度(这被称为"DOP Downgrade"),以避免系统过载 。

  4. 其他并行参数PARALLEL_DEGREE_POLICY参数的设置(如MANUAL, LIMITED, AUTO)以及PARALLEL_THREADS_PER_CPU等参数,也会影响Oracle对并行提示的响应方式和默认并行度的计算 。

3.3 如何监控和验证

要准确测量在特定环境下执行该语句时实际生成的进程数,可以采用以下方法:

  1. 在SQL执行期间,查询动态性能视图 V$PX_PROCESSV$PX_SESSION,可以清晰地看到协调者和所有被分配的并行执行服务器(Slaves)的状态和数量 。
  2. 通过查询 V$SESSION,可以关联协调者会话(QC Session)和其下属的并行执行会话。
  3. 在操作系统层面,可以通过 ps -ef | grep ora_p 等命令来观察 ora_p***_SID 格式的并行进程的生灭情况。

4. 结论

本文对给定的并行 INSERT ... SELECT 语句进行了全面的分析,得出以下结论:

这个结论可以通过测试得出。

只有16个并行进程。

相关推荐
板凳坐着晒太阳3 小时前
ClickHouse 配置优化与问题解决
数据库·clickhouse
AAA修煤气灶刘哥4 小时前
服务器指标多到“洪水泛滥”?试试InfluxDB?
数据库·后端·面试
阿沁QWQ5 小时前
MySQL服务器配置与管理
服务器·数据库·mysql
程序新视界6 小时前
MySQL“索引失效”的隐形杀手:隐式类型转换,你了解多少?
数据库·mysql·dba
Logintern096 小时前
windows如何设置mongodb的副本集
数据库·windows·mongodb
RestCloud8 小时前
在制造业数字化转型浪潮中,数据已成为核心生产要素。然而,系统割裂、数据滞后、开发运维成本高等问题,却像顽固的 “数据枷锁”,阻碍着企业发展。ETLCloud与
数据库·postgresql
!chen8 小时前
【Spring Boot】自定义starter
java·数据库·spring boot
十碗饭吃不饱9 小时前
sql报错:java.sql.SQLSyntaxErrorException: Unknown column ‘as0‘ in ‘where clause‘
java·数据库·sql
我是Superman丶9 小时前
【优化】Mysql指定索引查询或忽略某个索引
数据库·mysql