Oracle SGA 优化

SGA(系统全局区)是 Oracle 数据库所有进程共享的核心内存区域,负责缓存数据块、SQL 执行计划、重做日志等关键信息。SGA 优化的本质是让尽可能多的热点数据和代码常驻内存,将磁盘 IO 减少到最低,从而将数据库整体性能提升 10-100 倍。

1、SGA 基础

1.1、什么是 SGA 优化

SGA 优化是通过调整内存管理模式、分配 SGA 总大小、优化各组件资源配比和操作系统内存配置,实现三个核心目标:

  • 提高缓存命中率:缓冲区命中率 > 95%,库缓存命中率 > 99%
  • 避免内存交换:SGA 完全驻留在物理内存中,不被交换到磁盘
  • 消除内存争用:解决缓冲池、共享池等组件的锁竞争问题

1.2、SGA 内存架构

SGA(所有进程共享)

  • 数据库缓冲池(Database Buffer Cache):占比50-70%,缓存数据块(最核心)
    • DEFAULT池:默认缓冲池
    • KEEP池:缓存频繁访问的小表/索引
    • RECYCLE池:缓存偶尔访问的大表
  • 共享池(Shared Pool):占比15-25%,缓存SQL执行计划和数据字典
    • 库缓存(Library Cache):SQL/PL/SQL执行计划
    • 字典缓存(Row Cache):数据字典信息
  • 重做日志缓冲区(Redo Log Buffer):占比1-2%,缓存重做日志
  • 大池(Large Pool):RMAN备份、并行查询、共享服务器
  • Java池(Java Pool):Java程序执行
  • 流池(Streams Pool):Oracle Streams、GoldenGate

1.3、SGA 优化核心原则

  • 内存优先原则:SGA 占物理内存的 50-70%,至少保留 20% 给操作系统
  • 自动管理优先:生产环境使用 ASMM 模式,禁止手动管理
  • 大页必配原则:所有 Linux 生产环境必须配置大页,禁用透明大页
  • 按需分配原则:OLTP 系统侧重缓冲池,OLAP 系统侧重共享池和大池

2、核心组件优化

2.1、数据库缓冲池优化

数据库缓冲池缓存了从磁盘读取的数据块,是 SGA 中最大的组件,通常占 SGA 的 40-60%。

核心指标:缓冲区命中率:

计算缓冲区命中率:

SELECT

ROUND(1 - (physical_reads / (db_block_gets + consistent_gets)) * 100, 2) AS buffer_hit_ratio

FROM v$buffer_pool_statistics

WHERE name = 'DEFAULT';

命中率标准

  • 优秀:>99%
  • 良好:95-99%
  • 需优化:<95%

优化方法:

1、调整缓冲池大小

查看缓冲池大小建议:

SELECT size_for_estimate, buffers_for_estimate, estd_physical_read_factor

FROM v$db_cache_advice;

-- 调整缓冲池大小

ALTER SYSTEM SET DB_CACHE_SIZE=8G SCOPE=BOTH;

2、使用多缓冲池

  • DEFAULT 池:默认缓冲池,存储大多数数据
  • KEEP 池:存储频繁访问的小表和索引,避免被换出
  • RECYCLE 池:存储偶尔访问的大表,避免污染默认池

创建KEEP池和RECYCLE池:

ALTER SYSTEM SET DB_KEEP_CACHE_SIZE=1G SCOPE=BOTH;

ALTER SYSTEM SET DB_RECYCLE_CACHE_SIZE=2G SCOPE=BOTH;

将表分配到KEEP池:

ALTER TABLE emp STORAGE (BUFFER_POOL KEEP);

将表分配到RECYCLE池:

ALTER TABLE large_table STORAGE (BUFFER_POOL RECYCLE);

3、调整大小

  • OLTP 系统:使用 8KB 或 16KB 块大小
  • OLAP 系统:使用 32KB 或 64KB 块大小

2.2、共享池优化

共享池缓存了 SQL 执行计划、PL/SQL 代码和数据字典信息,通常占 SGA 的 15-25%。

核心指标:库缓存命中率和字典缓存命中率:

库缓存命中率:

SELECT ROUND(1 - (reloads / pins) * 100, 2) AS library_cache_hit_ratio

FROM v$librarycache;

字典缓存命中率:

SELECT ROUND(1 - (getmisses / gets) * 100, 2) AS dictionary_cache_hit_ratio

FROM v$rowcache;

命中率标准

  • 库缓存命中率:>99%
  • 字典缓存命中率:>95%

优化方法:

1、使用绑定变量:避免硬解析,这是共享池优化最重要的方法

不好的写法:每次执行都硬解析

SELECT * FROM emp WHERE empno=7369;

SELECT * FROM emp WHERE empno=7370;

好的写法:使用绑定变量,只硬解析一次

SELECT * FROM emp WHERE empno=:empno;

2、调整共享池大小:

查看共享池大小建议:

SELECT size_for_estimate, estd_lc_size, estd_lc_memory_objects

FROM v$shared_pool_advice;

调整共享池大小:

ALTER SYSTEM SET SHARED_POOL_SIZE=2G SCOPE=BOTH;

3、设置 CURSOR_SHARING 参数:

强制将字面量转换为绑定变量(临时解决方案):

ALTER SYSTEM SET CURSOR_SHARING=FORCE SCOPE=BOTH;

4、解决 ORA-04031 错误:

刷新共享池(临时解决):

ALTER SYSTEM FLUSH SHARED_POOL;

永久解决:增大共享池大小,优化SQL使用绑定变量

2.3、重做日志缓冲区优化

重做日志缓冲区缓存了即将写入磁盘的重做日志,通常设置为 64MB-256MB。

优化方法:

设置重做日志缓冲区大小:

ALTER SYSTEM SET LOG_BUFFER=64M SCOPE=SPFILE;

注意:重做日志缓冲区不是越大越好,超过 128MB 后性能提升不明显。

2.4、大池优化

大池用于 RMAN 备份、并行查询和共享服务器模式,通常设置为 100MB-1GB。

设置大池大小:

ALTER SYSTEM SET LARGE_POOL_SIZE=512M SCOPE=BOTH;

实例:大池不足导致 RMAN 备份超时

S(Situation - 情境): 某公司核心数据库每日全量备份时间从 2 小时延长至 6 小时,超出备份窗口。RMAN 日志显示大量 ORA-04031: unable to allocate 4194320 bytes of shared memory ("large pool") 错误。大池仅配置 100MB,RMAN 使用 4 个并行通道。

**T(Task - 任务):**当天解决备份超时问题,不影响夜间业务。

A(Action - 行动):

1、在线调整大池大小从 100MB 增至 2GB:ALTER SYSTEM SET LARGE_POOL_SIZE=2G SCOPE=BOTH;

2、调整 RMAN 并行通道数从 4 个增至 8 个

3、重新执行备份验证

**R(Result - 结果):**备份时间从 6 小时缩短至 1 小时 40 分钟,并不再出现 ORA-04031 错误,最终备份窗口完全满足业务要求。

相关推荐
Maynor9962 小时前
Codex API 网关迁移与流量优化实战
数据库·oracle
南极企鹅3 小时前
MySQL的两大支柱:undo Log&redo log
数据库·mysql·oracle
C137的本贾尼7 小时前
InnoDB 内存架构:Buffer Pool、Change Buffer 与 Log Buffer
数据库·oracle·架构
Bert.Cai7 小时前
SQLPlus简介
数据库·oracle
C137的本贾尼14 小时前
磁盘结构与关键日志:Redo Log、Undo Log 与双写缓冲区
服务器·数据库·oracle
六月雨滴15 小时前
Oracle PGA 优化
oracle·dba
IT邦德15 小时前
Oracle 26ai RAC 通过gold image RU打补丁
数据库·oracle
Minxinbb16 小时前
TDSQL for MySQL部署选型
数据库·dba
C137的本贾尼16 小时前
【实战】实现一个带事务与索引的命令行图书借阅系统
数据库·microsoft·oracle