重庆思庄Oracle、KingBase、PostgreSQL、Redhat认证学习论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 276|回复: 0
打印 上一主题 下一主题

[性能调整] session_cached_cursors参数的作用

[复制链接]
跳转到指定楼层
楼主
发表于 2025-12-27 12:25:26 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
session_cached_cursors 控制会话级游标缓存的大小。它决定每个数据库会话可以在其 PGA 中缓存的已解析 SQL 语句(游标)的数量。

工作原理--

游标解析的三个阶段

    1.硬解析(Hard Parse)

        检查语法

        语义检查

        生成执行计划

        最消耗资源

    2.软解析(Soft Parse)

        在共享池中找到已解析的游标

        较少资源消耗

    3.软软解析(Soft Soft Parse)

        在会话游标缓存中找到游标

        几乎不消耗资源

缓存机制--
text-

应用请求 SQL
    ↓
检查会话游标缓存    ←─ session_cached_cursors 控制
    ↓ 命中 → 直接执行(软软解析)
    ↓ 未命中
检查共享池
    ↓ 命中 → 放入会话缓存 → 执行(软解析)
    ↓ 未命中
硬解析 → 放入共享池 → 放入会话缓存 → 执行

参数配置--

查看当前设置
sql-

-- 查看参数值
SELECT name, value, description
FROM v$parameter
WHERE name = 'session_cached_cursors';

-- 或使用 show 命令
SHOW PARAMETER session_cached_cursors;

-- 查看所有会话的游标缓存使用情况
SELECT sid, value
FROM v$sesstat s, v$statname n
WHERE n.statistic# = s.statistic#
AND n.name = 'session cursor cache count'
ORDER BY value DESC;

推荐设置
sql-

-- 通常建议的设置
ALTER SYSTEM SET session_cached_cursors = 200 SCOPE=BOTH;

-- 对于OLTP高并发系统
ALTER SYSTEM SET session_cached_cursors = 300 SCOPE=BOTH;

-- 对于数据仓库系统(通常较低)
ALTER SYSTEM SET session_cached_cursors = 50 SCOPE=BOTH;

监控和诊断
1. 检查游标缓存命中率
sql

-- 系统级游标缓存命中率
SELECT 'session cursor cache hits' metric,
       ROUND(a.value/b.value*100, 2) value
FROM v$sysstat a, v$sysstat b
WHERE a.name = 'session cursor cache hits'
AND b.name = 'parse count (total)';

-- 会话级游标缓存命中率
SELECT s.sid, s.username,
       a.value "Cache Hits",
       b.value "Total Parses",
       ROUND(a.value/b.value*100, 2) "Cache Hit Ratio"
FROM v$sesstat a, v$sesstat b, v$statname c, v$statname d, v$session s
WHERE a.statistic# = c.statistic#
AND b.statistic# = d.statistic#
AND s.sid = a.sid
AND s.sid = b.sid
AND c.name = 'session cursor cache hits'
AND d.name = 'parse count (total)'
AND b.value > 0
ORDER BY 5 DESC;

2. 检查是否需要调整
sql

-- 检查游标缓存溢出
SELECT 'session cursor cache count' metric,
       SUM(value) value
FROM v$sesstat s, v$statname n
WHERE n.statistic# = s.statistic#
AND n.name = 'session cursor cache count';

-- 检查游标缓存使用情况
SELECT sid,
       s.value "Cached Cursors",
       (SELECT value FROM v$parameter WHERE name = 'session_cached_cursors') "Max Cache"
FROM v$sesstat s, v$statname n
WHERE n.statistic# = s.statistic#
AND n.name = 'session cursor cache count'
AND s.value > 0
ORDER BY s.value DESC;

3. 查找高解析的SQL
sql

-- 查找硬解析最多的SQL
SELECT sql_text, parse_calls, executions,
       parse_calls/executions parse_ratio,
       loads, invalidations
FROM v$sql
WHERE parse_calls > 1000
AND executions > 0
ORDER BY parse_calls DESC;

-- 查找可能受益于游标缓存的SQL
SELECT sql_id, sql_text,
       parse_calls, executions,
       loads, invalidations
FROM v$sql
WHERE parse_calls/executions > 0.1  -- 每次执行都解析
AND executions > 100
ORDER BY parse_calls DESC;

优化建议--

何时需要增加 session_cached_cursors?
sql

-- 检查指标,如果以下条件成立,可能需要增加
SELECT
  (SELECT value FROM v$sysstat WHERE name = 'parse count (hard)') hard_parses,
  (SELECT value FROM v$sysstat WHERE name = 'parse count (total)') total_parses,
  (SELECT value FROM v$sysstat WHERE name = 'session cursor cache hits') cache_hits,
  ROUND(
    (SELECT value FROM v$sysstat WHERE name = 'session cursor cache hits') /
    (SELECT value FROM v$sysstat WHERE name = 'parse count (total)') * 100, 2
  ) cache_hit_ratio
FROM dual;

-- 如果以下情况出现,考虑增加:
-- 1. cache_hit_ratio < 90%
-- 2. 硬解析率 > 10%
-- 3. 共享池存在大量游标老化


设置调整步骤
sql-

-- 1. 先监控当前值
SELECT sid, username,
       ss.value "Cached Cursors",
       sp.value "Max Cache"
FROM v$sesstat ss, v$statname sn, v$session s, v$parameter sp
WHERE ss.statistic# = sn.statistic#
AND ss.sid = s.sid
AND sp.name = 'session_cached_cursors'
AND sn.name = 'session cursor cache count'
AND ss.value > 0
ORDER BY ss.value DESC;

-- 2. 逐步增加(每次增加20-50)
ALTER SYSTEM SET session_cached_cursors = 150 SCOPE=BOTH;

-- 3. 监控效果
-- 等待一段时间后再次检查命中率

与其他参数的关系
open_cursors vs session_cached_cursors
sql-

-- open_cursors: 最大同时打开的游标数(防止泄漏)
-- session_cached_cursors: 缓存已关闭但可能重用的游标数

SHOW PARAMETER open_cursors;
SHOW PARAMETER session_cached_cursors;

-- 建议关系:open_cursors 应该是 session_cached_cursors 的 3-5 倍

shared_pool_size 影响
sql-

-- 共享池大小会影响硬解析频率
SHOW PARAMETER shared_pool_size;

-- 如果共享池太小,即使有游标缓存也无效
-- 因为父游标可能已被挤出共享池

最佳实践--

1. 应用层优化
sql

-- 使用绑定变量(最重要!)
-- 坏的写法
SELECT * FROM employees WHERE employee_id = 100;
SELECT * FROM employees WHERE employee_id = 101;

-- 好的写法(使用绑定变量)
SELECT * FROM employees WHERE employee_id = :emp_id;

2. 中间件配置
sql

-- 对于连接池(如WebLogic, Tomcat等)
-- 确保连接池配置了语句缓存
-- WebLogic: Statement Cache Size
-- Tomcat: preparedStatementCacheSize

3. 监控脚本
sql

-- 创建定期监控脚本
CREATE OR REPLACE PROCEDURE monitor_cursor_cache IS
  v_cache_hits NUMBER;
  v_total_parses NUMBER;
  v_hit_ratio NUMBER;
BEGIN
  SELECT SUM(DECODE(name, 'session cursor cache hits', value, 0)),
         SUM(DECODE(name, 'parse count (total)', value, 0))
  INTO v_cache_hits, v_total_parses
  FROM v$sysstat
  WHERE name IN ('session cursor cache hits', 'parse count (total)');
  
  IF v_total_parses > 0 THEN
    v_hit_ratio := ROUND(v_cache_hits / v_total_parses * 100, 2);
   
    IF v_hit_ratio < 90 THEN
      DBMS_OUTPUT.PUT_LINE('警告:游标缓存命中率偏低:' || v_hit_ratio || '%');
      -- 可以发送警报邮件
    END IF;
   
    INSERT INTO cursor_cache_stats
    VALUES (SYSDATE, v_hit_ratio, v_cache_hits, v_total_parses);
  END IF;
END;
/

-- 定期执行
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name => 'MONITOR_CURSOR_CACHE',
    job_type => 'PLSQL_BLOCK',
    job_action => 'BEGIN monitor_cursor_cache; END;',
    start_date => SYSTIMESTAMP,
    repeat_interval => 'FREQ=HOURLY',
    enabled => TRUE
  );
END;
/

常见问题解决--
问题1:ORA-01000: maximum open cursors exceeded
sql

-- 增加 open_cursors
ALTER SYSTEM SET open_cursors = 500 SCOPE=BOTH;

-- 检查应用是否有游标泄漏
SELECT s.sid, s.username, s.program,
       s.value "Open Cursors",
       (SELECT value FROM v$parameter WHERE name = 'open_cursors') "Max Cursors"
FROM v$sesstat s, v$statname n
WHERE n.statistic# = s.statistic#
AND n.name = 'opened cursors current'
AND s.value > 100
ORDER BY s.value DESC;

问题2:高硬解析率
sql

-- 增加 session_cached_cursors
ALTER SYSTEM SET session_cached_cursors = 300 SCOPE=BOTH;

-- 增加 shared_pool_size
ALTER SYSTEM SET shared_pool_size = 2G SCOPE=BOTH;

-- 使用绑定变量

问题3:PGA内存压力
sql

-- 如果PGA内存紧张,可能需要降低 session_cached_cursors
-- 检查PGA使用
SELECT * FROM v$pgastat;

-- 检查每个会话的PGA使用
SELECT sid, username,
       pga_used_mem/1024/1024 pga_used_mb,
       pga_alloc_mem/1024/1024 pga_alloc_mb,
       pga_max_mem/1024/1024 pga_max_mb
FROM v$process p, v$session s
WHERE p.addr = s.paddr
ORDER BY pga_used_mem DESC;

---------------------总结---------------------

session_cached_cursors 的关键点:

    作用:减少软解析,实现"软软解析"

    默认值:通常为50,但经常需要调整

    监控:关注命中率,目标 > 90%

    优化:配合绑定变量使用效果最佳

    平衡:与 open_cursors 和 shared_pool_size 协同调整

推荐设置范围:

    OLTP系统:200-500

    数据仓库:50-100

    混合型:100-200



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 支持支持 反对反对
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|重庆思庄Oracle、Redhat认证学习论坛 ( 渝ICP备12004239号-4 )

GMT+8, 2026-4-17 18:47 , Processed in 0.224039 second(s), 26 queries .

重庆思庄学习中心论坛-重庆思庄科技有限公司论坛

© 2001-2020

快速回复 返回顶部 返回列表