PGA 内存结构与 Private SQL Area

适用版本:Oracle Database 11g / 12c / 19c / 23ai
文档版本:v1.0 / 2026-07


1. 概述

PGA(Program Global Area) 是单个服务器进程私有的内存区,与 SGA 共享内存相对[1]。

核心特性:

  • 私有性:每个服务器进程独立 PGA
  • 非共享:进程间不互相访问
  • 动态分配:按需分配/释放
  • 会话级:随会话创建/销毁

2. PGA 主要组件

组件 作用
Private SQL Area SQL 绑定变量、执行状态
Sort Area 排序内存
Hash Area 哈希连接内存
Bitmap Merge Area 位图合并
Bitmap Create Area 位图创建
Stack 进程栈

3. Private SQL Area

3.1 作用

存储会话私有的 SQL 执行状态:

  • 绑定变量值
  • 排序区域指针
  • 游标执行状态

3.2 结构

Private SQL Area
├── Run-time Area(运行时区)
│   ├── 查询执行状态
│   ├── 已读取行数
│   └── 排序状态
└── Persistent Area(持久区)
    ├── 绑定变量值
    └── 排序缓冲区指针

3.3 专用 vs 共享服务器

模式 Private SQL Area 位置
专用服务器 PGA 中
共享服务器 UGA 中(位于 SGA 的 Shared Pool 或 Large Pool)

4. Work Area(工作区)

4.1 类型

类型 用途
Sort Area ORDER BY、DISTINCT、GROUP BY
Hash Area Hash Join、Hash Group By
Bitmap Merge Bitmap 索引合并
Bitmap Create Bitmap 索引创建

4.2 大小控制

SHOW PARAMETER pga_aggregate_target;
SHOW PARAMETER pga_aggregate_limit;
SHOW PARAMETER workarea_size_policy;
-- AUTO: 自动管理(推荐)
-- MANUAL: 手动(旧版)

4.3 排序区大小

-- 手动模式下的排序区大小
SHOW PARAMETER sort_area_size;
SHOW PARAMETER sort_area_retained_size;

5. PGA 自动管理

5.1 PGA_AGGREGATE_TARGET

-- 设置 PGA 目标总量
ALTER SYSTEM SET pga_aggregate_target=2G SCOPE=BOTH;

-- PGA 单个 Work Area 最大
-- = MIN(pga_aggregate_target * 5%, 100MB)

5.2 PGA_AGGREGATE_LIMIT(12c+)

-- 设置 PGA 硬上限
ALTER SYSTEM SET pga_aggregate_limit=4G SCOPE=BOTH;

-- 超过限制时:
-- 1. 终止内存消耗最大的会话
-- 2. 报 ORA-04036 错误

5.3 自动分配策略

PGA 总量 = pga_aggregate_target

分配规则:
- 单会话串行操作:最多 3% PGA
- 单会话并行操作:最多 50% PGA(分给所有并行进程)
- 多会话共享:动态平衡

6. 相关视图

-- PGA 总体统计
SELECT name, value/1024/1024 AS mb
FROM v$pgastat
WHERE name IN (
  'total PGA allocated',
  'total PGA used',
  'total PGA inuse',
  'total freeable PGA memory',
  'maximum PGA allocated',
  'aggregate PGA target parameter',
  'aggregate PGA auto target'
);

-- PGA 内存按会话分布
SELECT 
  pid, 
  spid, 
  program, 
  pga_used_mem/1024/1024 AS used_mb,
  pga_alloc_mem/1024/1024 AS alloc_mb,
  pga_max_mem/1024/1024 AS max_mb
FROM v$process
ORDER BY pga_alloc_mem DESC;

-- Work Area 统计
SELECT 
  work_area_size/1024/1024 AS size_mb,
  policy,
  optimal_executions,
  onepass_executions,
  multipasses_executions
FROM v$sql_workarea;

-- Work Area 建议器
SELECT 
  round(pga_target_for_estimate/1024/1024) AS pga_mb,
  estd_pga_cache_hit_percentage AS hit_pct,
  estd_overalloc_count AS overalloc
FROM v$pga_target_advice;

7. 排序性能诊断

7.1 监控排序

SELECT name, value 
FROM v$sysstat 
WHERE name LIKE '%sort%';
-- sort(memory): 内存中完成的排序
-- sort(disk): 写入磁盘的排序
-- 健康标准:sort(memory)/(sort(memory)+sort(disk)) > 95%

7.2 临时表空间使用

SELECT 
  username,
  sql_id,
  blocks * 8192/1024/1024 AS mb_used
FROM v$tempseg_usage
ORDER BY blocks DESC;

8. 常见坑与排错

8.1 排序溢出磁盘

现象:sort(disk) 比例高。

修复:

-- 1. 增大 PGA
ALTER SYSTEM SET pga_aggregate_target=4G SCOPE=BOTH;

-- 2. 优化 SQL 减少排序
-- 3. 检查临时表空间大小
SELECT tablespace_name, SUM(bytes)/1024/1024 AS mb 
FROM dba_temp_files 
GROUP BY tablespace_name;

8.2 ORA-04036: PGA 超过限制

现象:单会话占用 PGA 过多。

修复:

-- 1. 增大 pga_aggregate_limit
ALTER SYSTEM SET pga_aggregate_limit=8G SCOPE=BOTH;

-- 2. 优化消耗内存的 SQL(如大排序/哈希)
SELECT sql_id, pga_used_mem/1024/1024 AS mb
FROM v$sql_workarea_active
ORDER BY pga_used_mem DESC;

8.3 共享服务器 PGA 异常

现象:共享服务器模式下 PGA 使用过大。

原因:UGA 位于 SGA 中,PGA 主要存 Stack。

修复:检查 UGA 在 Shared Pool/Large Pool 的占用。


9. 最佳实践

  1. 使用 PGA 自动管理:workarea_size_policy=AUTO
  2. 合理设置 PGA_AGGREGATE_TARGET:通常是 SGA 的 20-30%
  3. 设置 PGA_AGGREGATE_LIMIT:硬上限 = 2×TARGET
  4. 监控排序溢出:sort(memory) 比例 > 95%
  5. 优化大排序 SQL:避免不必要的排序
  6. 临时表空间充足:≥ PGA 大小
  7. 并行查询注意 PGA:并行度高时 PGA 需求大

10. 参考资料

[1] Oracle Database Concepts 19c, “Program Global Area (PGA)”
https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/memory-architecture.html

[2] Oracle Database Administrator’s Guide 19c, “Managing PGA”
https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-memory.html