PGA 内存结构与 Private SQL Area

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 AreaSQL 绑定变量、执行状态
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 AreaORDER BY、DISTINCT、GROUP BY
Hash AreaHash Join、Hash Group By
Bitmap MergeBitmap 索引合并
Bitmap CreateBitmap 索引创建

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