加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

truncate后insert /*+append*/会利用initial extent吗?

(2006-09-30 10:19:29)
分类: Oracle学习
truncate后insert /*+append*/会利用initial extent吗?

今天看了Tom的文章,说会利用。不会浪费

但我的理解:truncate会把HWM降到initial extent以上,而insert append是从HWM以上开始插入数据的,因此会浪费掉initial extent。

到底是怎样呢?

SQL> create table test_extent as select * from dba_users;
Table created.
SQL> select file_id,extent_id,blocks
  from dba_extents where segment_name = 'TEST_EXTENT';
   FILE_ID  EXTENT_ID     BLOCKS
---------- ---------- ----------
                         8
SQL> insert into test_extent select * from test_extent;
5 rows created.
SQL> /
10 rows created.
SQL> /
20 rows created.
SQL> /
40 rows created.
SQL> /
40960 rows created.
SQL> commit;
Commit complete.
SQL> select file_id,extent_id,blocks
   from dba_extents where segment_name = 'TEST_EXTENT';
   FILE_ID  EXTENT_ID     BLOCKS
---------- ---------- ----------
                         8
                         8
                         8
                         8
                         8
                         8
                         8
                         8
                         8
                         8
                10          8
   FILE_ID  EXTENT_ID     BLOCKS
---------- ---------- ----------
                11          8
                12          8
                13          8
                14          8
                15          8
                16        128
                17        128
                18        128
                19        128
                20        128
                21        128
   FILE_ID  EXTENT_ID     BLOCKS
---------- ---------- ----------
                22        128
                23        128
24 rows selected.
SQL> truncate table test_extent;
Table truncated.
SQL> select file_id,extent_id,blocks
  from dba_extents where segment_name = 'TEST_EXTENT';
   FILE_ID  EXTENT_ID     BLOCKS
---------- ---------- ----------
                         8
---看到没,这时只剩下init extent,这是因为Oracle是以extent为最小分配单元的。
---下面看看此时的HWM:
SQL> select file_id,block_id
  from dba_extents where segment_name = 'TEST_EXTENT';
   FILE_ID   BLOCK_ID
---------- ----------
             34785
SQL> alter system dump datafile 1 block 34785;
System altered.
---Dump文件中的主要信息:
buffer tsn: 0 rdba: 0x004087e1 (1/34785)
scn: 0x0000.40097c7b seq: 0x01 flg: 0x00 tail: 0x7c7b1001
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 7    
                 last map  0x00000000  #maps: 0      offset: 4128  
   Highwater::  0x004087e2  ext#: 0      blk#: 0      ext size: 7 
---HWM指向segment header下面的一个Block。
---此时我们用insert /*+append*/看看 会不会从HWM下面的block开始才写数据?
SQL>  insert /*+append*/ into test_extent (select * from dba_users);
5 rows created.
SQL> commit;
Commit complete.
SQL> alter system dump datafile 1 block 34785;
System altered.
---Dump文件中的主要信息:
buffer tsn: 0 rdba: 0x004087e1 (1/34785)
scn: 0x0000.40097d47 seq: 0x02 flg: 0x00 tail: 0x7d471002
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 7    
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x004087e3  ext#: 0      blk#: 1      ext size: 7
---看到没,按照我们之前的假设:它应该是从之前的HWM的下一个Block分配单元,即0x004087e3 开始存储数据,并且此时的HWM应该指向:0x004087e4。但是事实却并非如此。
---继续:
SQL> insert /*+append*/ into test_extent (select * from dba_users);
5 rows created.
SQL> commit;
Commit complete.
SQL> alter system dump datafile 1 block 34785;
System altered.
---Dump文件中的主要信息:
buffer tsn: 0 rdba: 0x004087e1 (1/34785)
scn: 0x0000.40097daf seq: 0x02 flg: 0x00 tail: 0x7daf1002
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 7    
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x004087e4  ext#: 0      blk#: 2      ext size: 7 
---至此:我发现我之前的理解有点错误:
---原来:insert /*+append*/ 这种方式插入数据的时候是直接从HWM指向的Block开始插入数据,并不用再向下移一个Block,我之前一直以为会向下移一个Block。insert /*+append*/ 这种方式插入数据即使HWM下的Block还有空间可以存放数据也是不会去使用这些空间的,而是直接从HWM指向的地方开始存放数据。
 
---还有这里必须要区分init extent 和HWM这两个概念:
init extent: object创建时,初始分配的extent。一般是8 个Block,有一个是segment header ,所以可用的实际上只有7个block。(blocksize = 8K环境中)
HWM:这是一个segment的高水位,是对segment而言的。并且HWM有可能指向init extent 中的Block,两都并不是隔离的。
 
---总结:
TOM说的肯定是对的!truncate后insert /*+append*/会利用initial extent的。
 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有