Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1765127
  • 博文数量: 323
  • 博客积分: 5970
  • 博客等级: 大校
  • 技术积分: 2764
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-03 23:13
文章分类

全部博文(323)

文章存档

2018年(2)

2017年(11)

2016年(10)

2015年(27)

2014年(2)

2013年(30)

2012年(197)

2011年(44)

分类: Oracle

2012-05-06 19:29:01

中的临时表

临时表通常用来保存一个事务或者会话期间的数据.
临时表中保存的数据是具有独立性的,只对各自会话可见,并且每个会话
都只能查询和修改属于此会话的数据,在对 作dml操作时,
不需要申请锁资源,因此语句对于临时表来说是没有作用的.

在方面,在创建永久性表时通常是需要为表分配initial extent,但是对于
临时表是不需要的,临时表只是在使用的时候,根据数据来分配创建临时段.


对临时表的 DML 操作不会产生数据修改的重做日志,但是将产生被修改数据的撤销记录,

及撤销记录的重做日志.

我们来看一下临时表所产生的redo size情况.

SQL> select * from v$sesstat where sid=159 and statistic#=134;

       SID STATISTIC#      VALUE
---------- ---------- ----------
       159        134     929956

SQL> create global temporary table temp_ses on     
  2  commit preserve rows
  3  as
  4  select * from dba_objects;

Table created.

SQL> select * from v$sesstat where sid=159 and statistic#=134;

       SID STATISTIC#      VALUE
---------- ---------- ----------
       159        134     948420


再来看一下创建一个同样大小数据量的永久性表:
SQL> select * from v$sesstat where sid=142 and statistic#=134;

       SID STATISTIC#      VALUE
---------- ---------- ----------
       142        134       1432

SQL> create table pert as select * from dba_objects;

Table created.

SQL> select * from v$sesstat where sid=142 and statistic#=134;

       SID STATISTIC#      VALUE
---------- ---------- ----------
       142        134    5724360

SQL> select 5724360-1432 from dual;

5724360-1432
------------
     5722928

SQL>


可以看到两者的差距已经不仅仅是一个数据级了.

 

临时表一共有两种:
会话级别和事务级别的.

先来看一个会话级别的.

SQL> create global temporary table tmp_ses on commit preserve rows
  2  as  select * from dba_objects;

Table created.

SQL>

on commit preserve rows表明这一个基于会话的临时表,在会话断开以后.
所有数据都将被抹去.


SQL> create global temporary table tmp_trans on commit delete rows
  2  as select * from dba_objects;

Table created.

SQL>

on commit delete rows表示这是一个基于事务的临时表,在会话提交的时候,数据

就会被自动清除掉。

SQL> insert into tmp_trans select * from dba_objects;

49772 rows created.

SQL> select count(*) from tmp_trans;

  COUNT(*)
----------
     49772

SQL> commit;

Commit complete.

SQL> select count(*) from tmp_trans;

  COUNT(*)
----------
         0

这里可以看到在事务commit以后,临时表中的数据被全部清空。而这个清空的过程

是几乎不存在开销,oracle完成的仅仅是把临时段回收的一个动作。


临时段的分配

临时表使用临时段来分配数据,因此在创建临时表的时候,oracle并不会为其分配段,

而是在使用的时候才分配。我们可以使用v$sort_usage来观察某个临时表所占用的

空间大小。

SQL> select * from v$sort_usage;

no rows selected

SQL> insert into tmp_ses select * from dba_objects;

49772 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from tmp_ses;

  COUNT(*)
----------
     49772

SQL> select distinct sid from v$mystat;

       SID
----------
       142

SQL> select sid,serial# from v$session where sid=142;

       SID    SERIAL#
---------- ----------
       142        168

SQL>  select username,user,session_num,
  2  tablespace segtype,segfile#,segblk# ,blocks from v$sort_usage;

USERNAME   USER       SESSION_NUM SEGTYPE      SEGFILE#    SEGBLK#     BLOCKS
---------- ---------- ----------- ---------- ---------- ---------- ----------
TEST       TEST               168 TEMP              201       2313        768


这里可以看到,通过与v$session视图中的serial#相关联,可以得出某个会话的

所拥有的临时表中的数据的大小,当然,这里与永久表一样,在delete的时候

是不会释放出空间的:

SQL> select username,user,session_num,tablespace segtype,segfile#,segblk# ,blocks from v$sort_usage;

USERNAME   USER       SESSION_NUM SEGTYPE      SEGFILE#    SEGBLK#     BLOCKS
---------- ---------- ----------- ---------- ---------- ---------- ----------
TEST       TEST               168 TEMP              201       2313        768

SQL> delete tmp_ses;

19772 rows deleted.

SQL> commit;

Commit complete.

SQL> select count(*) from tmp_ses;

  COUNT(*)
----------
         0

SQL> select username,user,session_num,tablespace segtype,segfile#,segblk# ,blocks from v$sort_usage;

USERNAME   USER       SESSION_NUM SEGTYPE      SEGFILE#    SEGBLK#     BLOCKS
---------- ---------- ----------- ---------- ---------- ---------- ----------
TEST       TEST               168 TEMP              201       2313        768

SQL>


SQL> truncate table tmp_ses;

Table truncated.

SQL>  select username,user,session_num,tablespace segtype,segfile#,segblk# ,blocks from v$sort_usage;

no rows selected


可以看到,在删除数据时,oracle采用了节省成本的方式,减少了不必要的开销。


关于临时表的事务,与事务相关的临时表中的数据可以被用户的事务及子事务访问。

但是这些数据不能被同一会话里的两个事务同时访问。不同会话中的事务可以同时

使用同一个事务相关的临时表。如果用户事务对临时表执行了 INSERT 操作,

在此之后此事务的子事务将不能使用这个临时表。

如果在子事务中对临时表执行了 INSERT 操作,临时表中已有的数据将被清除。

子事务结束后,父事务及其他子事务对此临时表访问权利将被。
 

阅读(879) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~