Oracle PGA 与排序优化

Oracle PGA 与排序优化

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


1. 概述

PGA(Program Global Area) 是会话私有内存[1]:

组成

  • 私有 SQL 区
  • 排序区
  • 会话内存
  • 游标状态

2. PGA 管理

2.1 自动 PGA

ALTER SYSTEM SET pga_aggregate_target = 4G;
ALTER SYSTEM SET pga_aggregate_limit = 8G;  -- 12c+

2.2 手动

ALTER SESSION SET sort_area_size = 1048576;
ALTER SESSION SET sort_area_retained_size = 524288;
ALTER SESSION SET workarea_size_policy = MANUAL;

2.3 查看

SHOW PARAMETER pga
SHOW PARAMETER workarea

SELECT 
  name, 
  value / 1024 / 1024 AS mb
FROM v$pgastat;

3. 排序

3.1 排序来源

  • ORDER BY
  • GROUP BY
  • DISTINCT
  • UNION/INTERSECT/MINUS
  • SORT MERGE JOIN
  • CREATE INDEX
  • ANALYZE

3.2 内存 vs 磁盘

内存排序:sorts (memory)
磁盘排序:sorts (disk)

3.3 查看

SELECT 
  name, 
  value
FROM v$sysstat
WHERE name LIKE '%sort%';

3.4 命中率

SELECT 
  SUM(decode(name, 'sorts (memory)', value, 0)) AS mem_sorts,
  SUM(decode(name, 'sorts (disk)', value, 0)) AS disk_sorts,
  ROUND(
    SUM(decode(name, 'sorts (memory)', value, 0)) /
    NULLIF(SUM(decode(name, 'sorts (memory)', value, 'sorts (disk)', value, 0)), 0) * 100,
    2
  ) AS hit_pct
FROM v$sysstat
WHERE name IN ('sorts (memory)', 'sorts (disk)');

4. 工作区

4.1 类型

  • Optimal:完全内存
  • One-Pass:内存+一次磁盘
  • Multi-Pass:多次磁盘(慢)

4.2 查看

SELECT 
  low_optimal_size / 1024 AS low_kb,
  high_optimal_size / 1024 AS high_kb,
  total_executions,
  total_optimal_executions AS optimal,
  total_onepass_executions AS onepass,
  total_multipass_executions AS multipass
FROM v$sql_workarea_histogram
WHERE total_executions > 0;

4.3 PGA Advisory

SELECT 
  pga_target_for_estimate / 1024 / 1024 AS mb,
  estd_pga_cache_hit_percentage AS hit_pct,
  estd_overalloc_count
FROM v$pga_target_advice;

5. 排序优化

5.1 增大 PGA

ALTER SYSTEM SET pga_aggregate_target = 8G;

5.2 索引排序

-- 索引已排序
CREATE INDEX idx_emp_sal ON employees(salary);

SELECT * FROM employees WHERE dept_id = 10 ORDER BY salary;
-- 索引已排序,无需额外排序

5.3 避免不必要排序

-- 1. 索引覆盖
-- 2. 减少 ORDER BY
-- 3. UNION ALL 替代 UNION

5.4 并行排序

SELECT /*+ PARALLEL(4) */ * FROM big_table ORDER BY col;

6. 临时表空间

6.1 查看

SELECT 
  file_name,
  bytes / 1024 / 1024 AS mb,
  autoextensible
FROM dba_temp_files;

6.2 大小

-- 足够大
CREATE TEMPORARY TABLESPACE temp 
  TEMPFILE '/u01/oradata/orcl/temp01.dbf' SIZE 10G
  AUTOEXTEND ON NEXT 1G;

6.3 多临时文件

ALTER TABLESPACE temp ADD TEMPFILE '/u02/oradata/orcl/temp02.dbf' SIZE 10G;

7. 排序监控

7.1 活跃排序

SELECT 
  s.sid,
  s.serial#,
  s.username,
  s.program,
  w.operation,
  w.policy,
  w.estimated_optimal_size / 1024 AS est_kb,
  w.last_memory_used / 1024 AS used_kb
FROM v$session s, v$sql_workarea_active w
WHERE s.sid = w.sid;

7.2 临时段使用

SELECT 
  username,
  session_addr,
  sql_id,
  blocks * 8 / 1024 AS mb
FROM v$sort_usage
ORDER BY blocks DESC;

7.3 临时表空间使用

SELECT 
  tablespace_name,
  SUM(bytes_used) / 1024 / 1024 AS used_mb,
  SUM(bytes_free) / 1024 / 1024 AS free_mb
FROM v$temp_space_header
GROUP BY tablespace_name;

8. 大排序场景

8.1 CREATE INDEX

-- 增大 PGA
ALTER SESSION SET workarea_size_policy = MANUAL;
ALTER SESSION SET sort_area_size = 1073741824;  -- 1G

CREATE INDEX idx_big ON big_table(col);

ALTER SESSION SET workarea_size_policy = AUTO;

8.2 大表 GROUP BY

-- 并行
SELECT /*+ PARALLEL(8) */ 
  dept_id, COUNT(*), SUM(salary)
FROM big_table
GROUP BY dept_id;

8.3 大表 JOIN

-- Hash Join
SELECT /*+ USE_HASH(a b) PARALLEL(8) */ 
  a.id, b.name
FROM big_table_a a, big_table_b b
WHERE a.id = b.id;

9. 常见坑与排错

9.1 大量磁盘排序

-- 1. 增大 PGA
ALTER SYSTEM SET pga_aggregate_target = 8G;

-- 2. 优化 SQL
-- 3. 加索引

9.2 临时表空间满

-- 1. 增大
ALTER TABLESPACE temp ADD TEMPFILE '...' SIZE 5G;

-- 2. 查找大用户
SELECT * FROM v$sort_usage ORDER BY blocks DESC;

9.3 ORA-04036: PGA 不足

-- 增大 PGA_AGGREGATE_LIMIT
ALTER SYSTEM SET pga_aggregate_limit = 16G;

10. 最佳实践

  1. 自动 PGA 管理:默认
  2. PGA 25% 物理内存:合理
  3. PGA_AGGREGATE_LIMIT:12c+ 防失控
  4. 临时表空间足够:避免满
  5. 索引排序:减少排序
  6. UNION ALL:避免排序
  7. 并行大排序:性能
  8. 监控命中率:> 99%
  9. 定期 OPTIMIZE:临时段
  10. PGA Advisory:指导

11. 参考资料

[1] Oracle Database Performance Tuning Guide 19c, “PGA Memory” https://docs.oracle.com/en/database/oracle/oracle-database/19/tgdba/memory.html