PGA(程序全局区)是 Oracle 数据库中每个服务器进程私有的内存区域,专门用于处理 SQL 执行过程中的排序、哈希连接、位图合并等私有操作。PGA 优化的核心是让尽可能多的内存密集型操作在内存中完成,避免频繁读写临时表空间,从而将 SQL 执行速度提升 10-100 倍。
一、PGA 基础
1.1、什么是 PGA 优化
PGA 优化是通过调整 PGA 管理模式、分配总内存大小、优化 SQL 执行逻辑和限制进程资源使用,实现以下三个核心目标:
- 提高 Optimal 执行比例:让 90% 以上的内存操作在内存中完成
- 避免 Multi-pass 执行:完全杜绝多次读写临时表空间的情况
- 防止内存溢出:限制单个进程的 PGA 使用,避免数据库 OOM 崩溃
1.2、PGA 内存架构
PGA(每个进程私有)
- 工作区(Work Area):SQL执行的核心内存
- 排序区(Sort Area):ORDER BY/GROUP BY/DISTINCT/UNION
- 哈希连接区(Hash Area):大表哈希连接
- 位图合并区(Bitmap Merge Area):位图索引合并
- 聚合区(Aggregation Area):SUM/AVG/COUNT等聚合函数
- 会话内存(Session Memory)
- 游标状态
- 会话变量
- 堆栈空间
1.3、PGA vs SGA 核心区别
| 对比维度 | PGA | SGA |
|---|---|---|
| 共享性 | 每个进程私有 | 所有进程共享 |
| 用途 | 排序、哈希连接、聚合 | 缓存数据块、SQL 执行计划 |
| 大小 | 随进程动态变化 | 相对固定 |
| 优化重点 | 减少磁盘排序和哈希 | 提高缓存命中率 |
1.4、PGA 优化核心原则
- 自动管理优先:生产环境必须使用自动 PGA 管理,禁止手动管理
- 按需分配:OLAP 系统侧重 PGA(占总内存 30-40%),OLTP 系统侧重 SGA(占总内存 60-70%)
- 上限控制:必须设置 PGA_AGGREGATE_LIMIT,防止单个进程耗尽所有内存
- SQL 优化优先:优化 SQL 减少排序和哈希连接,比单纯增加内存更有效
二、PGA 管理模式
1、自动 PGA 管理
Oracle 9i 及以上版本支持自动 PGA 管理,这是生产环境的推荐方式。
启用自动PGA管理:
ALTER SYSTEM SET WORKAREA_SIZE_POLICY=AUTO SCOPE=BOTH;
设置PGA总大小:
ALTER SYSTEM SET PGA_AGGREGATE_TARGET=4G SCOPE=BOTH;
设置PGA最大限制(防止单个进程消耗过多内存):
ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=8G SCOPE=SPFILE;
2、核心指标:工作区执行方式
Oracle 将工作区执行分为三种方式:
- Optimal:所有操作都在内存中完成,性能最好
- One-pass:需要将部分数据写入临时表空间,性能中等
- Multi-pass:需要多次读写临时表空间,性能极差
优化目标:Optimal 执行比例 > 90%,One-pass<10%,完全避免 Multi-pass。
sql
-- 1. 查看PGA整体使用情况
SELECT
name,
value/1024/1024 AS value_mb
FROM v$pgastat
WHERE name IN (
'total PGA allocated',
'total PGA inuse',
'maximum PGA allocated'
);
-- 2. 查看工作区执行统计(最核心)
SELECT
optimal_executions,
onepass_executions,
multipasses_executions,
ROUND(optimal_executions/(optimal_executions+onepass_executions+multipasses_executions)*100, 2) AS optimal_pct
FROM v$pgastat
WHERE name IN ('optimal executions', 'onepass executions', 'multipasses executions');
-- 3. 查看PGA使用TOP 10进程
SELECT
s.sid,
s.serial#,
s.username,
s.program,
ROUND(p.pga_alloc_mem/1024/1024, 2) AS pga_alloc_mb,
ROUND(p.pga_used_mem/1024/1024, 2) AS pga_used_mb
FROM v$session s
JOIN v$process p ON s.paddr = p.addr
WHERE s.username IS NOT NULL
ORDER BY p.pga_alloc_mem DESC
FETCH FIRST 10 ROWS ONLY;
-- 4. 查看当前活跃的大工作区
SELECT
sql_id,
operation_type,
expected_size/1024/1024 AS expected_mb,
actual_mem_used/1024/1024 AS actual_mb,
number_passes
FROM v$sql_workarea_active
ORDER BY actual_mem_used DESC;
3、优化方法
调整 PGA_AGGREGATE_TARGET 大小:
查看PGA大小建议:
SELECT pga_target_for_estimate, pga_target_factor, estd_time FROM v$pga_target_advice;
设置原则:
- OLTP 系统:PGA_AGGREGATE_TARGET = 总内存 × 20-30%
- OLAP 系统:PGA_AGGREGATE_TARGET = 总内存 × 30-40%
- PGA_AGGREGATE_LIMIT = PGA_AGGREGATE_TARGET × 2
优化排序操作:
排序是消耗 PGA 最多的操作,也是最容易优化的操作:
a、在排序列上创建索引:利用索引的有序性避免排序
避免ORDER BY排序:CREATE INDEX idx_orders_order_date ON orders(order_date) ONLINE;
b、只排序需要的列:避免 SELECT *
c、减少排序的数据量:尽早使用 WHERE 条件过滤数据
d、避免不必要的排序:去掉多余的 ORDER BY、DISTINCT 和 UNION(改用 UNION ALL)
优化哈希连接:
- 小表驱动大表:让小表作为哈希表,减少内存消耗
- 在连接列上创建索引:减少连接的数据量
- 避免大表之间的哈希连接:改用嵌套循环连接或分区裁剪
实例:PGA 不足导致月底报表超时
S(Situation - 情境): 某公司 ERP 系统月底成本核算报表执行时间从 15 分钟飙升至 3 小时。AWR 显示direct path write temp等待事件占总等待时间的 85%,Multi-pass 执行比例达到 12%。
**T(Task - 任务):**1 小时内优化 PGA,确保当天完成报表。
A(Action - 行动):
1、在线调整 PGA_AGGREGATE_TARGET 从 2GB 增至 8GB
2、设置 PGA_AGGREGATE_LIMIT=16GB
3、杀掉正在执行的慢报表进程,重新执行
**R(Result - 结果):**报表执行时间从 3 小时缩短至 12 分钟,Optimal 执行比例从 78% 提升至 96%,并将Multi-pass 执行比例降至 0%,最终当天顺利完成月底成本核算。