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

 找回密码
 注册

QQ登录

只需一步,快速开始

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

[参考文档] Oracle 11g 查看TEMP实际占用

[复制链接]
跳转到指定楼层
楼主
发表于 2024-11-6 17:48:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
收到一些库有会话占用了大量temp表空间的告警,通常的做法是查询v$sort_usage找到对应sql_id


  1. select *
  2.   from (select username,
  3.                session_addr,
  4.                sql_id,
  5.                contents,
  6.                segtype,
  7.                blocks * 8 / 1024 / 1024 mb
  8.           from v$sort_usage
  9.          order by blocks desc)
  10. where rownum <= 20;
复制代码
但有时会发现找出来的sql特别简单,怎么看都不像能占用几十几百G temp表空间的样子。
为什么从v$sort_usage找到的sql_id有时是错的?应该怎么找正确的sql_id?


关于第一个问题,查找了网上的一些文章,发现v$sort_usage的sql_id并不对应v$session的sql_id,它对应的是v$session的prev_sql_id有一个V$FIXED_VIEW_DEFINITION视图可以查看固定视图定义,查询可以看到v$sort_usage定义如下
  1. select * from V$FIXED_VIEW_DEFINITION where view_name='V$SORT_USAGE';
  2. --输出如下
  3. select  USERNAME , "USER" , SESSION_ADDR , SESSION_NUM , SQLADDR , SQLHASH, SQL_ID, TABLESPACE , CONTENTS , SEGTYPE , SEGFILE# , SEGBLK# ,EXTENTS , BLOCKS , SEGRFNO# from GV$SORT_USAGE where inst_id = USERENV('Instance');
复制代码

可以看到它来自GV$SORT_USAGE,再查看GV$SORT_USAGE的定义
  1. select * from V$FIXED_VIEW_DEFINITION where view_name='GV$SORT_USAGE';
  2. --输出如下
  3. select x$ktsso.inst_id,
  4.        username,
  5.        username,
  6.        ktssoses,
  7.        ktssosno,
  8.        prev_sql_addr,
  9.         prev_hash_value,
  10.         prev_sql_id,  ----------- 注意这个
  11.         ktssotsn,
  12.         decode(ktssocnt, 0, 'PERMANENT', 1, 'TEMPORARY'),
  13.         decode(ktssosegt,
  14.                1,
  15.                'SORT',
  16.                2,
  17.                'HASH',
  18.                3,
  19.                'DATA',
  20.                4,
  21.                'INDEX',
  22.                5,
  23.                'LOB_DATA',
  24.                6,
  25.                'LOB_INDEX',
  26.                'UNDEFINED'),
  27.         ktssofno,
  28.         ktssobno,
  29.         ktssoexts,
  30.         ktssoblks,
  31.         ktssorfno
  32.    from x$ktsso, v$session
  33.   where ktssoses = v$session.saddr
  34.     and ktssosno = v$session.serial#;

  35. -- 12.2.0.1
  36. SELECT so.inst_id,
  37.        username,
  38.        username,
  39.        ktssoses,
  40.        ktssosno,
  41.        prev_sql_addr,
  42.        prev_hash_value,
  43.        prev_sql_id,
  44.        ts.name,
  45.        DECODE (ktssotbst, 1, 'TEMPORARY', 'PERMANENT'),
  46.        DECODE (ktssosegt,
  47.                1, 'SORT',
  48.                2, 'HASH',
  49.                3, 'DATA',
  50.                4, 'INDEX',
  51.                5, 'LOB_DATA',
  52.                6, 'LOB_INDEX',
  53.                7, 'TEMP_UNDO',
  54.                'UNDEFINED'),
  55.        ktssofno,
  56.        ktssobno,
  57.        ktssoexts,
  58.        ktssoblks,
  59.        ktssorfno,
  60.        ktssotsnum,
  61.        so.con_id,
  62.        ktssosqlid
  63.   FROM x$ktsso so, v$session, v$tablespace ts
  64. WHERE     so.ktssotsnum = ts.ts#
  65.        AND so.con_id = ts.con_id
  66.        AND ktssoses = v$session.saddr
  67.        AND ktssosno = v$session.serial#
复制代码
可以看到v$sort_usage的sql_id对应的是v$session的prev_sql_id。如果当前sql是最新正在执行的语句,查出来的结果是对的;如果过后执行了其它sql,看到就是错误的语句。
真正查询消耗高temp表空间的sql语句应该为
  1. SELECT S.sid,
  2.        S.serial# sid_serial,
  3.        S.username,
  4.        S.osuser,
  5.        P.spid,
  6.        S.module,
  7.        S.program,
  8.        SUM(T.blocks) * TBS.block_size / 1024 / 1024 mb_used,
  9.        T.tablespace,
  10.         COUNT(*) sort_ops
  11.    FROM v$sort_usage T, v$session S, dba_tablespaces TBS, v$process P
  12.   WHERE T.session_addr = S.saddr
  13.     AND S.paddr = P.addr
  14.     AND T.tablespace = TBS.tablespace_name
  15.   GROUP BY S.sid,
  16.            S.serial#,
  17.            S.username,
  18.            S.osuser,
  19.            P.spid,
  20.            S.module,
  21.            S.program,
  22.            TBS.block_size,
  23.            T.tablespace
  24. HAVING SUM(blocks) > 10000 -- 80MB
  25.   ORDER BY sid_serial;
  26. --将sid代入下面sql查出真正的sql_id
  27. select ktssosqlid from x$ktsso, v$session where ktssoses = v$session.saddr and ktssosno = v$session.serial# and v$session.sid=2111;
复制代码
或者直接利用下面的sql
  1. select k.inst_id "INST_ID",  
  2.        ktssoses "SADDR",  
  3.        sid,  
  4.        ktssosno "SERIAL#",  
  5.        username "USERNAME",  
  6.        osuser "OSUSER",   
  7.        ktssosqlid "SQL_ID",  
  8.        ktssotsn "TABLESPACE",  
  9.        decode(ktssocnt, 0, 'PERMANENT', 1, 'TEMPORARY') "CONTENTS",  
  10.         --注意在12c的v$sort_usage定义中TABLESPACE和CONTENTS已经发生变化了。
  11.         decode(ktssosegt, 1, 'SORT', 2, 'HASH', 3, 'DATA', 4, 'INDEX',   
  12.            5, 'LOB_DATA', 6, 'LOB_INDEX' , 'UNDEFINED') "SEGTYPE",  
  13.         ktssofno "SEGFILE#",  
  14.         ktssobno "SEGBLK#",  
  15.         ktssoexts "EXTENTS",  
  16.         ktssoblks "BLOCKS",  
  17.         round(ktssoblks*p.value/1024/1024, 2) "SIZE_MB",  
  18.         ktssorfno "SEGRFNO#"  
  19. from x$ktsso k, v$session s,   
  20.       (select value from v$parameter where name='db_block_size') p   
  21. where ktssoses = s.saddr  
  22.    and ktssosno = s.serial#;
复制代码
v$sort_usage中的SEGTYPE列含义
  • SORT:SQL排序使用的临时段,包括order by、group by、union、distinct、窗口函数、建索引等产生的排序。
  • DATA:临时表(Global Temporary Table)存储数据使用的段。
  • INDEX:临时表上建的索引使用的段。
  • HASH:hash算法所使用的临时段。
  • LOB_DATA和LOB_INDEX:临时LOB使用的临时段。
    另外可以通过以下语句查看一段时间前占用temp表空间高的sql

  1. select *
  2.   from (select t.sample_time,
  3.            s.PARSING_SCHEMA_NAME,
  4.            t.sql_id,
  5.            t.sql_child_number as sql_child,
  6.            round(t.temp_space_allocated / 1024 / 1024 / 1024, 2) || ' G' as temp_used,
  7.            round(t.temp_space_allocated /
  8.                  (select sum(decode(d.autoextensible, 'YES', d.maxbytes, d.bytes))
  9.                     from dba_temp_files d),
  10.                   2) * 100 || ' %' as temp_pct,
  11.             t.program,
  12.             t.module,
  13.             s.SQL_TEXT
  14.        from v$active_session_history t, v$sql s
  15.       where t.sample_time > to_date('2019-07-15 22:00:00', 'yyyy-mm-dd hh24:mi:ss')
  16.         and t.sample_time < to_date('2019-07-15 23:00:00', 'yyyy-mm-dd hh24:mi:ss')
  17.         and t.temp_space_allocated is not null
  18.         and t.sql_id = s.SQL_ID
  19.       order by t.temp_space_allocated desc)
  20.   where rownum < 50
  21.   order by temp_used desc;
复制代码

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-28 15:16 , Processed in 0.079239 second(s), 21 queries .

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

© 2001-2020

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