
好的,我们将对 Oracle 数据库的并行执行(Parallel Execution)协调机制进行一场深入而全面的剖析。并行执行是 Oracle 处理海量数据的关键技术,理解其内部原理对于构建和优化数据仓库、BI 系统至关重要。
第一部分:官方技术详解
一、核心概念与作用
1. 什么是并行执行?
并行执行是一种** divide-and-conquer(分而治之)** 的技术。它将一个大型串行任务(如全表扫描、排序、连接)分解成多个较小的子任务,分配給多个从属进程(Parallel Execution Slaves) 同时处理,最后将结果整合。其核心目标是缩短单个大任务的响应时间,以牺牲更多硬件资源(CPU、I/O、内存)为代价。
2. 适用场景
- 数据仓库(DWH)/决策支持系统(DSS):处理大量数据的查询(
SELECT)、数据加载(INSERT /*+ APPEND */、CREATE TABLE AS SELECT)、DML(UPDATE、DELETE)和 DDL(CREATE INDEX、MOVE TABLE)。 - 大型批处理作业。
- OLTP 系统应谨慎使用,因其会消耗大量资源,可能影响其他并发操作。
二、内部架构与协调机制
并行执行的协调是一个经典的生产者-消费者模型,由以下核心组件协同完成:
1. 核心组件
-
查询协调器 (Query Coordinator, QC):
- 身份:即发起原始 SQL 语句的用户会话进程(如服务器进程)。
- 职责:
- 解析 SQL 语句,生成并行执行计划。
- 请求并分配从属进程(PX Slaves)。
- 指导从属进程执行任务(分发工作单元)。
- 接收从属进程返回的最终结果,并将其返回给用户。
-
并行执行服务器进程 (Parallel Execution Server Processes, PX Slaves):
- 来源:从并行从属进程池(由
PARALLEL_MIN_SERVERS和PARALLEL_MAX_SERVERS参数定义)中分配。通常由实例后台进程Pnnn(如 P000, P001)或特定服务器进程充当。 - 类型与角色:
- 生产者 (Producer) / 读取从属 (Reader Slaves):负责扫描数据块(如全表扫描)、应用过滤条件,并将处理后的数据行发送给消费者从属进程。一个从属进程可以同时是生产者和消费者。
- 消费者 (Consumer) / 处理从属 (Processor Slaves):接收生产者发送的数据行,执行更复杂的操作,如排序(
ORDER BY)、分组(GROUP BY)、哈希连接(HASH JOIN)等,最后将结果返回给 QC。
- 来源:从并行从属进程池(由
-
并行执行消息缓冲区 (Buffer) / 表队列 (Table Queue, TQ):
- 本质:这是进程间通信(IPC)的核心机制,通常是共享内存(Shared Memory) 中的一块区域,用于在生产者和消费者之间高效地传递数据行。
- 管理:每个数据流在执行计划中都有一个唯一的
TQ ID(如:TQ10000)来标识。
2. 协调过程详解(生产者-消费者模型)
以一个简单的并行全表扫描和排序为例:
SELECT /*+ PARALLEL(emp, 4) */ * FROM emp ORDER BY sal DESC;
假设并行度(DOP, Degree of Parallelism)为 4。
-
QC 生成计划与分配进程:
- QC 解析语句,优化器生成一个并行执行计划。计划中会包含
PX COORDINATOR,PX SEND,PX RECEIVE等操作。 - QC 从进程池中请求 4 个从属进程。通常,这 4 个进程会被分成两组:一组主要作为生产者负责扫描,另一组作为消费者负责排序。但在简单查询中,角色可能重叠。
- QC 解析语句,优化器生成一个并行执行计划。计划中会包含
-
工作单元分配 - Granule(粒度):
- QC 需要决定如何将大表
EMP分成小块(称为 Granules)分配给生产者进程。 - 两种Granule类型:
- Block Range Granules (最常见):将表划分为多个连续的块范围(如 blocks 1-1000, 1001-2000…)。每个生产者进程处理一个范围。适用于大多数操作。
- Partition Granules:如果表已分区,则直接按分区分配。一个生产者处理一个或多个完整分区。效率更高,因为消除了分区内的再分配。
- QC 需要决定如何将大表
-
生产者阶段:
- 每个生产者进程并行地、独立地扫描分配给它的那些数据块(Granules)。
- 它们应用
WHERE子句中的任何过滤条件(本例中没有)。 - 扫描出的数据行被立即放入表队列(TQ) 中,准备发送给消费者进程。数据在放入 TQ 前可能会被哈希分区或广播,以满足后续操作(如
JOIN或GROUP BY)的需求。在本例的ORDER BY中,数据需要根据sal的值进行重新分布,以便相同的sal值由同一个消费者处理进行排序。
-
消费者阶段:
- 消费者进程从 TQ 中取出数据行。
- 每个消费者进程对自己收到的数据子集进行局部排序(Partial Sort)。
- 完成局部排序后,消费者将有序的数据子集返回给 QC。
-
QC 最终处理:
- QC 从所有消费者进程那里接收已经局部排序的数据流。
- QC 执行最终归并排序(Merge Sort),将多个有序流合并成一个最终的有序结果集。
- QC 将最终结果返回给客户端。
3. 关键参数与管理机制
-
并行度 (DOP):
- 定义参与操作的从属进程数量。可以通过 Hint(
/*+ PARALLEL(table_name, degree) */)、表/索引级别设置(ALTER TABLE emp PARALLEL 4;)或会话/系统参数(ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4;)来指定。 PARALLEL_THREADS_PER_CPU参数帮助 Oracle 计算默认 DOP。PARALLEL_DEGREE_POLICY参数控制是否启用自动 DOP(AUTO)、并行语句排队(QUEUING)和内存优化(ADAPTIVE)。
- 定义参与操作的从属进程数量。可以通过 Hint(
-
自适应并行(
PARALLEL_DEGREE_POLICY=ADAPTIVE):- 优化器可能根据系统负载和对象大小动态调整 DOP。
- 如果预计执行时间很短,可能会选择串行执行以避免启动进程的开销。
-
并行语句排队(
PARALLEL_DEGREE_POLICY= AUTO | QUEUING):- 当请求的并行进程总数超过
PARALLEL_SERVERS_TARGET限制时,新的并行语句不会立即执行,而是进入一个队列等待资源可用。这防止了系统因过度并行化而崩溃。
- 当请求的并行进程总数超过
第二部分:场景、争用、排查与解决
四、性能争用与排查
并行执行虽然强大,但会显著增加系统资源的消耗,从而引发多种争用。
1. 场景:CPU 争用
- 原理:并行查询会尝试使用所有可用的 CPU 资源。如果多个高 DOP 的查询同时运行,或者 DOP 设置过高,会导致 CPU 利用率达到 100%,进程在运行队列中等待调度。
- 等待事件:
resmgr:cpu quantum(如果启用了资源管理器)或简单的CPU time在 AWR 报告中占比极高。 - 排查:
- 查看 AWR 报告的
Load Profile,观察CPU cores使用情况。 - 查看
Top 10 Foreground Events,如果CPU time是第一等待事件,说明 CPU 是瓶颈。
- 查看 AWR 报告的
- 解决:
- 合理设置
PARALLEL_MAX_SERVERS,防止系统创建过多从属进程。 - 使用
DBMS_RESOURCE_MANAGER来限制特定用户或组的 CPU 使用率和并行度。 - 调整
PARALLEL_DEGREE_POLICY为AUTO或LIMITED,让优化器更保守地选择 DOP。 - 优化 SQL 和减少 DOP,减少单个查询的 CPU 消耗。
- 合理设置
2. 场景:I/O 争用
- 原理:多个从属进程同时全表扫描或执行并行排序,会发出大量并发 I/O 请求,可能超过存储系统的 I/O 带宽(IOPS 或吞吐量)。
- 等待事件:
db file scattered read:常见于全表扫描的多块读操作。db file sequential read:索引查找或单块读。direct path read/direct path write:常见于并行扫描和并行排序的临时段 I/O,它 bypasses the buffer cache。
- 排查:
- AWR 报告中
Top 10 Foreground Events出现上述事件且平均等待时间很长。 I/O Profile部分显示高物理读/写。
- AWR 报告中
- 解决:
- 确保存储系统有足够的 I/O 能力(如更多磁盘、更快的 SSD)。
- 使用分区和智能扫描来减少物理 I/O 量。
- 优化
SORT_AREA_SIZE或PGA_AGGREGATE_TARGET以减少排序到磁盘的操作。
3. 场景:并行执行服务器进程争用
- 原理:当系统并发执行的并行语句过多时,可用的并行从属进程(
PARALLEL_MAX_SERVERS)可能被耗尽。新的并行语句将无法获得资源,或者已运行的语句可能因为等待进程而挂起。 - 等待事件:
PX Deq: Execute Reply:一个从属进程已完成工作,正在等待 QC 分配新任务。长时间的等待可能意味着 QC 或消费者进程是瓶颈。enq: PS - contention:保护并行从属进程池分配的锁争用。当进程频繁分配和释放时可能发生。PX Queuing: statement queue:当PARALLEL_DEGREE_POLICY设置为AUTO或QUEUING时,语句在等待进入执行队列时出现此等待。
- 排查:
- 查询
V$PX_PROCESS_SYSSTAT查看已分配和空闲的进程数。SELECT * FROM V$PX_PROCESS_SYSSTAT WHERE STATISTIC LIKE 'Servers%'; - 查询
V$SQL或 AWR 找到高 DOP 的 SQL。 - 检查
V$RSRC_CONSUMER_GROUP查看资源组的使用情况。
- 查询
- 解决:
- 适度增加
PARALLEL_MAX_SERVERS(需谨慎,避免过度配置)。 - 启用并行语句排队(
PARALLEL_DEGREE_POLICY=QUEUING)来平滑负载。 - 优化 SQL,降低其所需的 DOP。
- 适度增加
4. 场景:倾斜(Skew)导致的负载不均
- 原理:在生产者和消费者模型中,如果数据分布严重倾斜(例如,基于一个具有极不均匀值的列进行哈希连接或分组),会导致某些从属进程收到远超其他进程的数据量,形成“短板效应”,其他进程早已完工,却要等待那个忙碌的进程。
- 影响:并行执行效率远低于预期,资源利用不均。
- 排查:很难直接观察,需要通过执行计划推断,或使用 SQL 监控报告(
DBMS_SQLTUNE.REPORT_SQL_MONITOR)查看每个从属进程的工作量。 - 解决:
- 选择数据分布更均匀的连接键或分组键。
- 使用
/*+ PQ_DISTRIBUTE(table_name, HASH, HASH) */等 Hint 尝试不同的数据分发方法。
五、常用查询与管理 SQL
-
监控当前并行执行的语句:
SELECT sid, serial#, username, sql_id, degree, req_degree FROM v$session WHERE sid IN (SELECT qc_session_id FROM v$px_session); -
查看并行从属进程的详细会话信息:
-- 找出所有并行从属进程及其对应的 QC(查询协调器) SELECT s.sid, s.serial#, s.username, s.sql_id, s.status, pxs.qcsid AS QC_SID, pxs.server_group, pxs.server_set, pxs.degree FROM v$session s, v$px_session pxs WHERE s.sid = pxs.sid ORDER BY pxs.qcsid, pxs.server_group, pxs.server_set; -
查看并行进程池状态:
SELECT statistic, value FROM v$px_process_sysstat; -
生成 SQL 监控报告(极其强大,用于深入分析):
-- 首先从 V$SESSION 或 V$SQL 中找到要分析的 SQL_ID SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR( sql_id => '&sql_id', type => 'TEXT', report_level => 'ALL') AS report FROM dual; -- 该报告会显示并行执行计划的每个步骤、每个从属进程的工作量、时间线等信息。 -
调整对象的并行度:
ALTER TABLE sales PARALLEL 8; ALTER INDEX sales_idx PARALLEL 4; ALTER TABLE sales NOPARALLEL; -- 禁用并行
第三部分:通俗易懂的解释
想象一下你是一个总包工头(Query Coordinator, QC),要负责打扫一个巨大的、有100个房间的酒店(处理海量数据)。
-
串行执行:你一个人拿一把扫帚,从101房间开始,一个一个房间打扫下去。耗时极长。
-
并行执行:你采用了“分而治之”的策略。
- 招募工人(PX Slaves):你从劳务市场(Parallel Server Pool)雇了10个清洁工(DOP=10)。
- 分配任务(Granules):你把酒店平面图撕成10份,每人分10个房间(Block Range Granules)。“你去打扫1-10号房,你去11-20…”
- 工人干活(Producer):工人们同时开始,各自打扫自己的房间(并行全表扫描)。
- 收集垃圾(Table Queue):每个工人把扫出的垃圾装袋,放到走廊上一个指定的集合点(Table Queue, TQ),这个集合点对应着“可回收垃圾”或“不可回收垃圾”(数据分发方式)。
- 处理垃圾(Consumer):另外一组专门负责运输的工人(Consumer Slaves)从集合点取走垃圾袋,进行下一步处理,比如把塑料瓶压扁(排序、分组、连接)。
- 最终汇总(QC Merge):运输工人们把处理好的垃圾运到你这里。你把所有压扁的塑料瓶堆在一起,形成一座整齐的小山(归并排序),然后交给回收站(返回给客户端)。
会出现什么问题?(争用场景)
- CPU争用(工人累坏了):你雇了100个工人(DOP过高),但他们挤在走廊上,胳膊都抡不开了,大部分时间在互相躲让(上下文切换),效率反而下降。
- I/O争用(走廊堵了):工人们都推着小车去扔垃圾,但垃圾通道只有一个,大家全堵在门口排队(
direct path read等待)。 - 进程争用(招不到人):现在是保洁旺季,劳务市场里所有清洁工都被其他包工头雇走了(
PARALLEL_MAX_SERVERS耗尽),你找不到工人,你的工程只能干等着(PX Queuing)。 - 负载不均(Skew):你有个工人分到了10个总统套房,面积巨大;而另一个工人分到的10个是储物间,5分钟就扫完了。扫完的工人无所事事,必须等那个扫总统套房的工人完工(倾斜)。
如何管理?
- 作为一个聪明的包工头,你不会总是雇100个人。你会根据酒店大小(数据量)、当前酒店里其他包工头的活动(系统负载)、以及你的时间要求,来决定雇多少人(
DOP)。 - 你还会让来不及干的工程先拿个号排队(
PARALLEL_DEGREE_POLICY=QUEUING),而不是一窝蜂冲进去把劳务市场挤垮。
总结:
Oracle 并行执行是一个复杂但极其强大的协调系统。QC 是大脑,PX Slaves 是四肢,Table Queues 是神经系统。它的高效依赖于合理的资源分配(DOP)和均衡的工作负载。DBA 的角色就像是公司的调度总监,需要监控整个“工地”的资源使用情况,确保大型项目(并行查询)能高效完成,而不至于拖垮整个系统(资源争用)。通过 V$ 视图和 SQL 监控报告这些“监控摄像头”,你可以精准地定位到是哪个环节出现了拥堵,并采取相应的措施。
欢迎关注我的公众号《IT小Chen》
1364

被折叠的 条评论
为什么被折叠?



