你应该知道的临时表空间理论和常用SQL查询

【引言】
Oracle的表空间是Oracle数据库存储数据和对象的逻辑容器;

根据创建时语句的不同,种类为三种:
1.常规表空间(create tablespace or create bigfile tablespace…) permanent段
2.undo表空间(create undo ) undo段
3.临时表空间(create temporary) temporary段

Permanent类和undo类表空间,大家很熟悉了。
今天主要来说一下临时表空间temporary。

Oracle临时表空间主要是存储数据库的排序操作、临时表、中间排序结果等临时对象,其信息不需要REDO,因此临时表的DML操作往往比普通表产生的REDO少很多。临时表数据变化不产生REDO,UNDO数据变化产生RED;临时段不仅仅存在于临时表空间中,也可能存在普通表空间。比如通过CTAS(create table … as select)创建一张表,新表的数据放在临时段中,临时段在CTAS完成时会被转换为PERMENT段。

ORACLE7.3 推出的新算法的核心就是SEP(SORT EXTENT POOL),SEP 负责管理临时段中扩展的结构,存储在共享池内,任何需要使用排序空间的操作,都需要从SEP 中分配空闲的扩展,使用完毕后,不需要释放该空间,只需要在SEP 中将该扩展设置为空闲。

当数据库实例启动后,SMON 将会删除该实例未释放的临时段,并对临时表空间进行碎片整理。在这个操作完成前,数据库打开的操作不能完成。因此每次数据库重启后,临时段中的垃圾都会被完全清理。当数据库打开后,第一个进行的硬盘排序操作会在相关的临时表空间内创建临时段,这个临时段也是整个实例唯一的临时段(在新的临时段算法下,同一个表空间内,每个实例只有一个临时段)。临时段中扩展的信息会被记录在SEP 中。硬盘排序操作会在SEP 中查找可用的扩展,在查找前,需要获得SORT EXTENT POOL 闩锁。如果能找到可用的扩展,那么SEP 中已被分配的扩展就会被标注为占用状态;如果找不到可用的扩展,那么系统就会试图从表空间中分配新的空间,而如果这个分配工作因为表空间的空闲空间不足而无法完成,那么就会产生一个ORA-1652 错误。

当排序操作完成的时候,会再次获取SORT EXTENT POOL 闩锁,并且将使用的扩展标注为空闲,然后释放SORT EXTENT POOL 闩锁。新的临时表空间管理算法不需要频繁地分配和释放临时段,这大大提高了临时段管理的效率。由于这是一种只分配不释放的算法,因此DBA 经常会看到自己的临时表空间总是处于或者接近100%使用的状态。其实对于7.3 以后的版本而言,临时表空间使用率接近100%是十分正常的,DBA 可以通过V S O R T U S A G E 和 V SORT_USAGE 和V SORTUSAGEVSORT_SEGMENTS 这两个视图来检查临时段的使用情况。

在RAC 中,由于多个实例会共享一个临时表空间。在RAC环境下,每个实例都拥有独立的SEP,各实例中排序需在自己的SEP中分配空间。如SEP 中无法分配到足够的空间,若其他的rac节点实例还有空闲扩展,则可分配给需要的实例使用。注意: 此时虽然SERVER 进程不会收到ORA-1652 错误信息,但在ALTER LOG 中会有一个ORA-1652 记录。

了解了临时表空间基本原理,知道了在进行大数量级排序操作时,数据库内存不够时,中间结果会写入临时表空间,当操作完成后,临时表空间就会自动清空释放。Oracle经常使用到临时表空间的操作有:create index(创建索引)、group by(分组查询)、order by(排序时)、集合运算时(union、minus、intersect)、多表连接查询时,当数据库内存不足时,会用到临时表空间。

再来说一下占用临时表空间的几种常见情况:
1:order by or group by (disc sort占主要部分); 
2:索引的创建和重创建; 
3:distinct操作; 
4:union & intersect & minus sort-merge joins; 
5:analyze 操作。

常用的临时表空间操作管理SQL。
1.临时表空间表空间数据文件查看
SELECT file_name,
bytes / 1024 / 1024 / 1024,
status,
tablespace_name
FROM dba_temp_files;

2.如何查看临时表空间都是被什么SQL占用?
SELECT vt.inst_id,
vs.sid,
vs.serial#,
vs.machine,
vs.saddr,
vs.program,
vs.module,
vs.logon_time,
vt.tempseg_usage,
vt.segtype
FROM gv s e s s i o n v s , ( S E L E C T i n s t i d , u s e r n a m e , s e s s i o n a d d r , s e g t y p e , R O U N D ( S U M ( b l o c k s ) ∗ 8192 / 1024 / 1024 / 1024 , 2 ) t e m p s e g u s a g e F R O M g v session vs, ( SELECT inst_id, username, session_addr, segtype, ROUND (SUM (blocks) * 8192 / 1024 / 1024 / 1024, 2) tempseg_usage FROM gv sessionvs,(SELECTinstid,username,sessionaddr,segtype,ROUND(SUM(blocks)8192/1024/1024/1024,2)tempsegusageFROMgvtempseg_usage
GROUP BY inst_id,
username,
session_addr,
segtype
ORDER BY 4 DESC) vt
WHERE vs.inst_id = vt.inst_id AND vs.saddr = vt.session_addr
ORDER BY tempseg_usage DESC;

3.查询会话使用临时表空间
SELECT SE.USERNAME,
SE.SID,
  SE.SERIAL#,
  SE.SQL_ADDRESS,
  SE.MACHINE,
  SE.PROGRAM,
  SU.TABLESPACE,
 SU.SEGTYPE,
  SU.CONTENTS  FROM V S E S S I O N S E ,     V SESSION SE,   V SESSIONSE,  VSORT_USAGE SU  WHERE SE.SADDR = SU.SESSION_ADDR;

或者

SELECT B.TABLESPACE,
    B.SEGFILE#,
    B.SEGBLK#,
    B.BLOCKS,
    B.BLOCKS * 32 / 1024 / 1024,
    A.SID,
    A.SERIAL#,
    A.USERNAME,
    A.OSUSER,
    A.STATUS,
    C.SQL_TEXT,
    B.CONTENTS
FROM V S E S S I O N A , V SESSION A, V SESSIONA,VSORT_USAGE B, V$SQL C
WHERE A.SADDR = B.SESSION_ADDR
AND A.SQL_ADDRESS = C.ADDRESS(+)
and status = ‘ACTIVE’
ORDER BY B.BLOCKS DESC;

4.数据库中消耗资源比较大的SQL
SELECT se.username,
    se.sid,
    su.extents,
    su.blocks * TO_NUMBER (RTRIM (p.VALUE)) AS Space,
    tablespace,
    segtype,
    sql_text
FROM v s o r t u s a g e s u , v sort_usage su, v sortusagesu,vparameter p,
v s e s s i o n s e , v session se, v sessionse,vsql s
WHERE p.name = ‘db_block_size’
  and su.session_addr = se.saddr
  and s.hash_value = su.sqlhash
  and s.address = su.sqladdr
order by se.username, se.sid;

文章至此。

欢迎关注个人微信公众号“一森咖记”
image.png

猜你喜欢

转载自blog.csdn.net/db_murphy/article/details/110473670