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)负责并行地从表b
的p1
分区读取数据。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,极大地提升了大数据量加载的性能 。
- 与并行的协同 :
APPEND
与PARALLEL
结合使用是大数据仓库(DW)和ETL场景下的最佳实践,能够实现最高效的数据加载 。
2.3 并行查询 (Parallel Query) 与 SELECT
操作
语句的 SELECT
部分包含了 /*+ parallel 16 */
提示。这个提示独立地作用于查询操作,指示Oracle使用16的并行度来扫描源数据------即表 b
的 p1
分区 。
- 工作方式 :查询协调器(Query Coordinator)会将对
b
表p1
分区的扫描任务分解成多个数据块范围(rowid ranges or block ranges),然后分配给16个并行执行服务器去同时读取。
2.4 核心架构:生产者-消费者模型
当并行 INSERT
和并行 SELECT
结合在一条语句中时,Oracle的并行执行引擎会采用一个高效的生产者-消费者模型 。
- 生产者 (Producers) :一组并行执行服务器(由
SELECT
部分的parallel 16
提示请求)负责并行扫描表b
的分区p1
。它们是数据的生产者。 - 消费者 (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几乎不可能总是精确地按这个数字分配。实际生成的进程数是一个动态决策的结果,受到以下关键因素的制约:
-
PARALLEL_MAX_SERVERS
参数 :这是整个Oracle实例(Instance)中允许存在的并行执行服务器进程总数的硬性上限 。如果当前系统中活动的并行进程数加上本次请求的32个进程,超过了此参数的设定值,Oracle将无法满足请求。它可能会降低实际的并行度,甚至将操作排队等待或降级为串行执行 。 -
PARALLEL_SERVERS_TARGET
参数:这个参数在12c及以后版本中引入,定义了在SQL开始排队之前,实例允许运行的并行服务器进程的目标数量 。如果当前活动的进程数已经达到这个目标值,新的并行请求可能会被排队。 -
系统资源与负载:Oracle会实时评估CPU、内存和I/O的负载情况。如果系统资源紧张,即使配置参数允许,Oracle也可能会主动降低实际分配的并行度(这被称为"DOP Downgrade"),以避免系统过载 。
-
其他并行参数 :
PARALLEL_DEGREE_POLICY
参数的设置(如MANUAL
,LIMITED
,AUTO
)以及PARALLEL_THREADS_PER_CPU
等参数,也会影响Oracle对并行提示的响应方式和默认并行度的计算 。
3.3 如何监控和验证
要准确测量在特定环境下执行该语句时实际生成的进程数,可以采用以下方法:
- 在SQL执行期间,查询动态性能视图
V$PX_PROCESS
和V$PX_SESSION
,可以清晰地看到协调者和所有被分配的并行执行服务器(Slaves)的状态和数量 。 - 通过查询
V$SESSION
,可以关联协调者会话(QC Session)和其下属的并行执行会话。 - 在操作系统层面,可以通过
ps -ef | grep ora_p
等命令来观察ora_p***_SID
格式的并行进程的生灭情况。
4. 结论
本文对给定的并行 INSERT ... SELECT
语句进行了全面的分析,得出以下结论:
这个结论可以通过测试得出。
只有16个并行进程。