暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle PGA 深度解析

恩恩霸 2025-09-03
232

Oracle PGA 深度解析
——程序全局区的概念、结构、管理与优化

一、PGA 的定位与基本概念
在 Oracle 的内存体系里,SGA(System Global Area)被所有前台与后台进程共享,而 PGA(Program Global Area,程序全局区)则是**每个进程所独占**的内存区域。每当用户通过专用服务器模式(Dedicated Server)连接到实例,Oracle 都会为该会话派生一个新的服务器进程,并随之分配一块 PGA;在共享服务器模式(Shared Server)下,则把大部分私有数据迁移到 SGA 中的 Large Pool,但每个会话仍保留一个最小的 PGA。PGA 的主要职责是保存“会话私有”的运行时数据,使 SQL 执行、排序、哈希连接、PL/SQL 变量、游标句柄等操作不必抢占或污染共享内存,从而兼顾性能与隔离。

二、PGA 的组成结构
从 9i 到 19c,Oracle 把 PGA 的内存划分成四大子区,DBA 通过 v$process、pga_target_advice 等视图可以实时观察它们的大小与峰值。

1. 会话内存(Session Memory)
存放登录认证、会话级参数、NLS 环境、包变量、会话级触发器上下文等。专用服务器模式下这部分通常占 100 KB–2 MB;共享服务器模式下会显著缩小。

2. SQL 工作区(SQL Work Area)
这是 PGA 中**最活跃、最易膨胀**的部分,用于:
• 排序(Sort Area):ORDER BY、GROUP BY、DISTINCT、窗口函数、索引构建。
• 哈希(Hash Area):哈希连接、哈希聚合、位图索引合并。
• 位图合并区(Bitmap Merge Area)。
• 批量加载缓冲区(Direct Path Load Buffer)。
当工作区无法容纳全部数据时,Oracle 会自动把溢出段写入临时表空间,造成 I/O 抖动与性能陡降。

3. 游标与 SQL 区(Cursor & SQL Area)
包括私有 SQL 区(Private SQL Area)以及运行时堆栈。专用服务器模式下,私有 SQL 区完全位于 PGA;共享服务器模式下,Persistent Area 被移到 SGA,而 Runtime Area 仍留在 PGA。

4. UGA(User Global Area)
UGA 并不是独立物理区域,而是“逻辑概念”:专用服务器时 UGA 就是 PGA 的子集;共享服务器时 UGA 位于 SGA。它保存打开的游标、PL/SQL 表、集合、会话级对象缓存等信息。

三、PGA 的管理模式演进
1. 手动管理(PGA_AGGREGATE_TARGET=0)
早期版本通过 sort_area_size、hash_area_size、bitmap_merge_area_size 等参数逐条设定,粒度粗、易浪费,且无法防止“贪婪”会话挤爆内存。

2. 自动内存管理(AMM,10g 以后)
引入 PGA_AGGREGATE_TARGET,Oracle 采用“全局预算 + 动态反馈”算法:
• 实例启动时,MMAN 进程根据参数值扣除 SGA 后,把剩余物理内存的 80% 分配给 PGA。
• 每个进程首次申请工作区时,Oracle 会计算一个“期望大小”,并在会话之间动态收缩/扩张,保证总和不超过目标值。
• 通过 v$pga_target_advice、v$sysstat、AWR 报告中的“PGA Aggr”系列指标,可评估目标是否充足。

3. 混合模式与限制
若同时设置了 pga_aggregate_limit(11gR2 以后),则 PGA 总量一旦超过该硬性上限,Oracle 会终止最“耗内存”会话,防止 OOM。

四、SQL 工作区的内部算法
Oracle 按 OPTIMAL、ONEPASS、MULTIPASS 三级策略分配工作区:
• OPTIMAL:全部数据一次在内存完成,性能最佳。
• ONEPASS:数据分片一次写出、一次读回,仅一次额外 I/O。
• MULTIPASS:反复写读,性能最差。
通过 v$sql_workarea_active、v$sql_workarea_histogram 可以监控这三种级别出现的频率,进而调整 PGA 大小或改写 SQL。

五、PGA 与临时表空间的协作
当工作区不足时,Oracle 使用临时表空间中的临时段做“外排”。如果观察到 100% 的排序都在磁盘完成,应首先检查:
• PGA_AGGREGATE_TARGET 是否过小;
• 是否存在失控的笛卡尔乘积或缺失索引;
• 临时文件是否位于低速存储。
在 Exadata、ASM 或 SSD 环境下,可评估把临时表空间迁移到高速磁盘,以缓解 I/O 压力。

六、诊断与调优实战
1. 查看当前实例总体 PGA
SQL> select name,value from v$pgastat where name in ('aggregate PGA target parameter','total PGA inuse','total freeable PGA memory','over allocation count');

2. 找出最耗 PGA 的会话
SQL> select s.sid,s.serial#,p.pga_max_mem/1024/1024 MB,p.spid
from v$session s, v$process p
where s.paddr=p.addr order by 3 desc;

3. 评估 PGA 目标是否合适
SQL> select pga_target_for_estimate/1024/1024 MB,estd_pga_cache_hit_percentage hit_ratio
from v$pga_target_advice order by 1;
当 hit_ratio 连续多行接近 100% 时,说明当前目标已足够;若 90% 以下,则继续上调。

4. 处理 PGA 泄漏
在 PL/SQL 中大量使用 BULK COLLECT 或长时间保持游标不关闭,会导致 PGA 只增不减。应检查:
• LIMIT 子句是否缺失;
• DBMS_SQL 句柄是否及时关闭;
• 是否把大集合变量存储在包级全局变量。

七、与并行查询、并行 DML 的关系
并行执行时,每个并行子进程(PX slave)都会分配独立 PGA,其工作区大小受“parallel_execution_message_size”与“pga_aggregate_target”共同影响。对大型排序或哈希连接,应确保:
• pga_aggregate_target ≥ (并行度 × 预计单进程工作区) × 1.5;
• 临时表空间 I/O 带宽足够,防止 PX 进程互相阻塞。

八、PGA 在云与多租户环境下的变化
从 12c 开始,CDB 与 PDB 共享同一 PGA_AGGREGATE_TARGET。为了资源隔离,Oracle 引入:
• PDB 级参数 PGA_AGGREGATE_LIMIT;
• Resource Manager 计划,限制单个 PDB 的 PGA 上限;
• 通过 v$rsrc_pga_stats 查看每个 PDB 的实时 PGA 占用。

九、最佳实践总结
1. 在 OLTP 系统,建议 PGA_AGGREGATE_TARGET = (物理内存 × 20%);在 DSS/OLAP 系统可上调至 40%–60%。
2. 关闭 sort_area_size 等旧参数,避免与自动管理冲突。
3. 定期巡检 v$pgastat.over_allocation_count,若不为 0,则说明预算不足。
4. 把临时表空间放在本地 NVMe 或 ASM 高冗余磁盘,减少 MULTIPASS。
5. 对 PL/SQL 程序进行 Code Review,防止隐式游标、大集合变量长期持有。
6. 在 AWR 报告中关注“PGA Aggr”段,若“maximum PGA allocated”接近 pga_aggregate_limit,应提前扩容或优化 SQL。

结语
PGA 作为 Oracle 实例中唯一“进程独占”的内存区域,其大小与管理策略直接影响排序效率、哈希连接性能、会话并发度乃至系统稳定性。通过理解 PGA 的四大子区、掌握自动内存管理的算法、熟练运用诊断视图与 AWR 报告,并结合业务特征进行精细化调优,DBA 可以在保障会话隔离的同时,最大化系统吞吐与响应速度。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论