zoukankan      html  css  js  c++  java
  • Oracle 课程二之Oracle数据库逻辑结构

    完成本课程的学习后,您应该能够:

    •数据库总体的逻辑结构

    •深入理解数据库最小存储单元block
    •理解行迁移和行链接
    •理解高水位线
    •Drop、truncate、delete区别
     
    1.数据库的逻辑
      方案(schema)是一个逻辑数据结构的集合。每个数据库用户拥有一个与之同名的方案,且只有这一方案(详情请见concepts第5章)。

      数据库逻辑结构为数据块(Data Block)、数据扩展(Extent)、和段(Segment); 物理结构为数据文件。

      Block是最精细的数据存储粒度,一个数据块相当于磁盘上一段连续的物理存储空间,oracle每次访问数据的单位是block。

      Extent是为存储数据而分配的一组连续的block,只能在一个数据文件中。

      Segment则是由一个或多个Extent。一张表可以看做是一个段,一个索引可以做作是一个段。查看段的分类select distinct        segment_type from user_segments 。可以跨数据文件。

       数据逻辑上存储表空间(Tablespace)中,而物理上则存储于属于表空间的数据文件(data file)中。

    1.1表空间管理

    •字典管理

      依赖数据字典表来跟踪空间使用(已经过时)

    •本地管理(默认)

      使用位图(而不是数据字典表)来跟踪使用和空闲空间在表空间本地管理的情况下,Oracle先在表空间第一候选的数据文件上寻找可以分配给第一个区段的空间,然后查看数据文件的位图来查看是否有足够数目的空闲块。如果数据文件没有足够的空闲块,然后Oracle会转向新的数据文件。

    1.2段空间分配方式

    Uniform

    •对于统一大小区段,你可以指定区段大小或者使用默认大小,默认大小为1M。根据给定的块大小,要保证每个区段至少包含5个数据块。临时表空间管理区段的方式只能采取这种方式。

    AUTOALLOCATE

    •对于系统管理的区段,Oracle确定新增区段的最优大小,最小区段的大小是64K。如果表空间创建包括“segment space management auto”,如果数据库块大小是16k或者更高,然后Oracle管理段创建区段的最小尺寸是1M。这是持久表空间的默认管理方式。

    select * from dba_segments where owner='SCOTT';

    1.3表中的段分配

    一个表在创建之后,除非进行truncate,否则数据库段中分配的所有数据块都只属于这个表。Oracle在一个块有足够空间的情况下插入新行。甚至你删除了表的所有行,Oracle也不会释放数据块,表空间的其他对象也无法使用这些数据块。

    1.4索引的段分配

    只要索引存在,索引段中的所有区段都属于索引段。当你删除(drop)索引或者相关的表时,Oracle释放区段,本表空间的其他对象可以使用这部分空间。

    1.5临时段的段分配

    当Oracle执行完一个需要临时段的语句时,Oracle自动删除临时段。如果排序操作能够在内存中进行,Oracle不会创建这个段。

    1.6回滚段的段分配

    Oracle周期性的检查数据库的回滚段,来检查是否超过了它们的最优尺寸。如果回滚段远大于最优尺寸(也就是说,有太多的区段),然后Oracle会自动从回滚段中释放一个或者多个区段。

    1.7区的大小?

    在我们默认的本地管理表空间中,extent是通过bitmap位图块来管理,Oracle通过内部的算法来自动决定下一个extent的大小

    create table t(id number);select * from user_extents where segment_name='T'drop table t purge;
    create table t as select * from dba_objects;select * from user_extents where segment_name='T';
    View Code

    1.8小结:

    1.数据库有一个或多个表空间组成。
    2.表空间有一个或多个数据文件组成。
    3.段(TABLE、INDEX)有一个或多个区段组成。段在表空间中,但是可以包含这个表空间中多个数据文件中的数据。
    4.区段是磁盘上一组逻辑连续的块。区段只在一个表空间中,而且总是在改表空间内的一个文件中。
    5.块是数据库中最小的分配单元,也是数据库使用的最小I/O单元。
     
    2.block的内部结构
    seg/obj: 0x180a2  csc: 0x95a.e56f14c6  itc: 2  flg: E  typ: 1 - DATA
         brn: 0  bdba: 0x181e541 ver: 0x01 opc: 0
         inc: 0  exflg: 0
     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0002.002.000072bb  0x0081fa06.1e1c.26  --U-    2  fsc 0x0000.e56f14ce
    0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
     。。。。。。。。。。。省略。。。。。。。。。。。
    0x14:pri[1]    offs=0x1f88
    block_row_dump:
    tab 0, row 0, @0x1f90
    tl: 8 fb: --H-FL-- lb: 0x1  cc: 1
    col  0: [ 4]  d6 d0 b9 fa
    tab 0, row 1, @0x1f88 
    tl: 8 fb: --H-FL-- lb: 0x1  cc: 1
    col  0: [ 4]  c3 c0 b9 fa
    end_of_block_dump
    Dump文件的block信息

    dump的文件在 盘符:oracleproduct10.2.0adminordb10udump

    SQL>alter session set tracefile_identifier = 'Look_For_Me';
    SQL>create table test(name varchar2(10));
    SQL>insert into test values('中国');
    SQL>nsert into test values('美国');
    SQL>commit;
    SQL>select rowid,
           dbms_rowid.rowid_object(rowid) object_id,
           dbms_rowid.rowid_relative_fno(rowid) file_id,
           dbms_rowid.rowid_block_number(rowid) block_id,
           dbms_rowid.rowid_row_number(rowid) num
      from test;
    
    SQL>alter system dump datafile 6 block 124232;
    生成dump bock信息
    --在PL/SQL命令窗口要
    set serveroutput on
    --查看表
    exec show_space('watch_log_event','auto','table');
    exec show_space('watch_log_event','auto','table','Y');
    --查看索引
    exec show_space('INDEX_TX_LOCK','auto','index');
    exec show_space('INDEX_TX_LOCK','auto','index','Y');
    create or replace procedure show_space 
    ( p_segname_1 in varchar2, 
    p_space in varchar2 default 'MANUAL', 
    p_type_1 in varchar2 default 'TABLE' , 
    p_analyzed in varchar2 default 'N', 
    p_owner_1 in varchar2 default user) 
    as 
    p_segname varchar2(100); 
    p_type varchar2(10); 
    p_owner varchar2(30); 
    l_unformatted_blocks number; 
    l_unformatted_bytes number; 
    l_fs1_blocks number; 
    l_fs1_bytes number; 
    l_fs2_blocks number; 
    l_fs2_bytes number; 
    l_fs3_blocks number; 
    l_fs3_bytes number; 
    l_fs4_blocks number; 
    l_fs4_bytes number; 
    l_full_blocks number; 
    l_full_bytes number; 
    l_free_blks number; 
    l_total_blocks number; 
    l_total_bytes number; 
    l_unused_blocks number; 
    l_unused_bytes number; 
    l_LastUsedExtFileId number; 
    l_LastUsedExtBlockId number; 
    l_LAST_USED_BLOCK number; 
    procedure p( p_label in varchar2, p_num in number ) 
    is 
    begin 
    dbms_output.put_line( rpad(p_label,40,'.') || 
    p_num ); 
    end; 
    begin 
    p_segname := upper(p_segname_1); 
    p_owner := upper(p_owner_1); 
    p_type := p_type_1; 
    
    if (p_type_1 = 'INDEX' or p_type_1 = 'index') then  
    p_type := 'INDEX'; 
    end if; 
    if (p_type_1 = 'TABLE' or p_type_1 = 'table') then  
    p_type := 'TABLE'; 
    end if; 
    if (p_type_1 = 'CLUSTER' or p_type_1 = 'cluster') then  
    p_type := 'CLUSTER'; 
    end if; 
    
    dbms_space.unused_space 
    ( segment_owner => p_owner, 
    segment_name => p_segname, 
    segment_type => p_type, 
    total_blocks => l_total_blocks, 
    total_bytes => l_total_bytes, 
    unused_blocks => l_unused_blocks, 
    unused_bytes => l_unused_bytes, 
    LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId, 
    LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId, 
    LAST_USED_BLOCK => l_LAST_USED_BLOCK ); 
    
    if p_space = 'MANUAL' or (p_space <> 'auto' and p_space <> 'AUTO') then 
    dbms_space.free_blocks 
    ( segment_owner => p_owner, 
    segment_name => p_segname, 
    segment_type => p_type, 
    freelist_group_id => 0, 
    free_blks => l_free_blks ); 
    
    p( 'Free Blocks', l_free_blks ); 
    end if; 
    
    p( 'Total Blocks', l_total_blocks ); 
    p( 'Total Bytes', l_total_bytes ); 
    p( 'Unused Blocks', l_unused_blocks ); 
    p( 'Unused Bytes', l_unused_bytes ); 
    p( 'Last Used Ext FileId', l_LastUsedExtFileId ); 
    p( 'Last Used Ext BlockId', l_LastUsedExtBlockId ); 
    p( 'Last Used Block', l_LAST_USED_BLOCK ); 
    
    
    /*IF the segment is analyzed */ 
    if p_analyzed = 'Y' then 
    dbms_space.space_usage(segment_owner => p_owner , 
    segment_name => p_segname , 
    segment_type => p_type , 
    unformatted_blocks => l_unformatted_blocks , 
    unformatted_bytes => l_unformatted_bytes, 
    fs1_blocks => l_fs1_blocks, 
    fs1_bytes => l_fs1_bytes , 
    fs2_blocks => l_fs2_blocks, 
    fs2_bytes => l_fs2_bytes, 
    fs3_blocks => l_fs3_blocks , 
    fs3_bytes => l_fs3_bytes, 
    fs4_blocks => l_fs4_blocks, 
    fs4_bytes => l_fs4_bytes, 
    full_blocks => l_full_blocks, 
    full_bytes => l_full_bytes); 
    dbms_output.put_line(rpad(' ',50,'*')); 
    dbms_output.put_line('The segment is analyzed'); 
    p( '0% -- 25% free space blocks', l_fs1_blocks); 
    p( '0% -- 25% free space bytes', l_fs1_bytes); 
    p( '25% -- 50% free space blocks', l_fs2_blocks); 
    p( '25% -- 50% free space bytes', l_fs2_bytes); 
    p( '50% -- 75% free space blocks', l_fs3_blocks); 
    p( '50% -- 75% free space bytes', l_fs3_bytes); 
    p( '75% -- 100% free space blocks', l_fs4_blocks); 
    p( '75% -- 100% free space bytes', l_fs4_bytes); 
    p( 'Unused Blocks', l_unformatted_blocks ); 
    p( 'Unused Bytes', l_unformatted_bytes ); 
    p( 'Total Blocks', l_full_blocks); 
    p( 'Total bytes', l_full_bytes); 
    end if; 
    end; 
    
     SQL> exec show_space('TEST','auto','table'); 
     
    Total Blocks............................8
    Total Bytes.............................65536
    Unused Blocks...........................0
    Unused Bytes............................0
    Last Used Ext FileId....................6
    Last Used Ext BlockId...................124225
    Last Used Block.........................8
    
    官方文档解释:
    
    
    Parameter Description 
    segment_owner
     Schema name of the segment to be analyzed.
     
    segment_name
     Segment name of the segment to be analyzed.
     
    segment_type
     Type of the segment to be analyzed (TABLE,INDEX, orCLUSTER):
    
    •TABLETABLE PARTITION
    
    •TABLE SUBPARTITION
    
    •INDEXINDEX PARTITION
    
    •INDEX SUBPARTITION
    
    •CLUSTER
    
    •LOB
    
    •LOB PARTITION
    
    •LOB SUBPARTITION
     
    total_blocks
     Returns total number of blocks in the segment.
     
    total_bytes
     Returns total number of blocks in the segment, in bytes.
     
    unused_blocks
     Returns number of blocks which are not used.
     
    unused_bytes
     Returns, in bytes, number of blocks which are not used.
     
    last_used_extent_ file_id
     Returns the file ID of the last extent which contains data.
     
    last_used_extent_ block_id
     Returns the starting block ID of the last extent which contains data.
     
    last_used_block
     Returns the last block within this extent which contains data.
     
    partition_name
     Partition name of the segment to be analyzed.
    
    This is only used for partitioned tables; the name of subpartition should be used when partitioning is compose.
    查看表和视图空间show_space()

    2.1Block内容解析--The Transaction Header

      一共占据48bytes,包括24bytes的控制信息,和一系列的Interested Transaction Slot (ITS)。这些ITS组合在一起称为Interested Transaction List (ITL)。初始的ITL slot 数量由 INITRANS 决定(index branch block 只有1个slot)。如果有足够的剩余空间,oracle会根据需要动态的分配这些slot,直到受到空间限制或者达到了MAXTRANS。

    •Object number(seg/obj): 占用4bytes,指在OBJ$中记录的segment 的 object number(0x806d=32877)
    •Cleanout SCN(csc):  占用6bytes,最后一次 full cleanout 的scn
    •ITL count(itc): 占用1byte,ITL 的slot数量。
    •Flag: 占用2bytes。O表示这个block在freelist 上。否则flag为”-”
    •Block type: 占用1byte。1=data; 2=index
    •ITL freelist slot(fsl): 占用1byte。Index to the first slot on the ITL freelist
    •Next freelist block(fnx): 占用4byte。Segment freelist中下一个block的RDBA
    •Version: 1 byte
    •Unused: 4bytes,用来前后兼容。
     

    1.要研究block中所有的含义,请参考http://blog.csdn.net/guogang83/article/details/8640555 

    2.二进制、八进制、十进制、十六进制的相互转换请参考http://blog.csdn.net/guogang83/article/details/8002014 

    select pkg_number_trans.f_hex_to_dec(‘1b5’) from dual;--十六进制转换为十进制

    2.2Block内容解析-- Data Area

      包括14bytes的data header,4bytes/table的table dictionary,2bytes/row的row dictionary。table dictionary主要用于cluster block中,只不过table block中的table dictionary只有一个table。

    •select  chr(to_number('d6d0','xxxx')) from dual;--中

    •select  chr(to_number('b9fa','xxxx'))  from dual;--国

    1.不同的数据类型解析规则不一样,想要知道更多的数据类型解析,请参考http://blog.csdn.net/guogang83/article/details/8010105

    实验2.2 Oracle如何实现行锁

      通过数据库的物理结构实现行锁

    insert into test values('韩国');
    insert into test values('朝鲜');
    insert into test values('越南');
    commit;
     alter system dump datafile 6 block 124232;
    
    重新开一个session:
    select * from test where name='韩国' for update;
    
    重新开一个session:
    select * from test where name='韩国' for update;
    行锁实验

    2.3Block参数PCTFREE、PCTUSED

    •PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert了,只能被用于update;即:当使用一个block时,在达到pctfree之前,该block是一直可以被插入的,这个时候处在上升期。
    •PCTUSED:是指当块里的数据低于多少百分比时,又可以重新被insert,一般默认是40,即40%,即:当数据低于40%时,又可以写入新的数据,这个时候处在下降期。
    • 注意:10g以后PCTUSED已经过时。
     

    思考题:建表时的参数含义?

    create table TEST(ID NUMBER) 

    tablespace DFWMS

      pctfree 10

      initrans 1

      maxtrans 255

      storage

      ( initial 64

         minextents 1

         maxextents unlimited

     );

    3.行迁移与行链接

     3.1 行迁移

      原本存储在一个数据块内的数据行,因为更新操作导致长度增长,而所在数据块的可用空间也不能容纳增长后的数据行。在这种情况下,oracle将此行数据迁移到新的数据块中,oracle在被迁移数据行原本所在位置保存一个指向新数据块的指针。被迁移数据行的rowid保持不变。当数据行发生链接或迁移时,对其访问将会造成I/O性能降低,因为oracle为获取这些数据行的数据时,必须访问更多的数据块。

    实验3.1:实验产生行迁移

      要想构造出行迁移,我们要有点特殊的手段,需要尽量让数据块满,只要把pctfree设置小一点就可以了。插入一些数据后,找到一个块满的,然后做修改,由于块中已没有空间支持行链接,则发生行迁移,是整行发生迁移。

    SQL>drop table t purge;
    SQL>select * from t;
    
    SQL>create table t
    (a varchar2(4000),
    b varchar2(4000),
    c varchar2(4000)) pctfree 2;
    
    SQL>begin 
      for i in 1.. 1000
               loop
        insert into t values(i,i,i);
         end loop;
          commit;
    end;
    
    SQL>select count(1),block_id from 
    (select rowid,a,
           dbms_rowid.rowid_object(rowid) object_id,
           dbms_rowid.rowid_relative_fno(rowid) file_id,
           dbms_rowid.rowid_block_number(rowid) block_id,
           dbms_rowid.rowid_row_number(rowid) num
      from t )group by block_id;
      
    SQL>select max(a) max_a,min(a) min_a from(select rowid,a,
           dbms_rowid.rowid_object(rowid) object_id,
           dbms_rowid.rowid_relative_fno(rowid) file_id,
           dbms_rowid.rowid_block_number(rowid) block_id,
           dbms_rowid.rowid_row_number(rowid) num
      from t) where block_id=1471;
      
     SQL>update t set b=lpad('2', 4000, '2'),c=lpad('2', 4000, '2')
    where to_number(a) >484 and to_number(a) <950;
      
    SQL>alter system dump datafile 4 block 1471;
    
    trace的文件:黄色部分就是行迁移
    tl: 9 fb: --H----- lb: 0x2  cc: 0nrid:  0x010005f0.0tab 0, row 10, @0x1e89tl: 9 fb: --H----- lb: 0x2  cc: 0nrid:  0x010005f7.0tab 0, row 11, @0x1e80tl: 9 fb: --H----- lb: 0x2  cc: 0nrid:  0x010005f1.0tab 0, row 12, @0x1e77tl: 9 fb: --H----- lb: 0x2  cc: 0nrid:  0x010005f3.0tab 0, row 13, @0x1e43tl: 52 fb: --H-F--N lb: 0x2  cc: 2nrid:  0x010005f4.0col  0: [ 3]  34 39 38col  1: [38] 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
    
    
    转换nrid:
    select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047bc',
                                                          'xxxxxxxxxx')) file#,
           dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047bc',
                                                           'xxxxxxxxxx')) block#
      from dual;  
    实验一个行迁移例子

    3.2 行链接

      当一行数据被插入时一个数据块就无法容纳,在这种情况下oracle将这行数据存储在段内的一个数据块链中。在插入数据量大的行时常会发生行链接(row chaining)。例如一个包含数据类型为long或long raw列的数据行,此时行链接不可避免。

    SQL>create table t
    (a varchar2(4000),
    b varchar2(4000),
    c varchar2(4000));     insert into t values
    (lpad('1', 4000, '1'),
    lpad('2', 4000, '2'),
    lpad('3', 4000, '3'));  commitselect rowid,
           dbms_rowid.rowid_object(rowid) object_id,
           dbms_rowid.rowid_relative_fno(rowid) file_id,
           dbms_rowid.rowid_block_number(rowid) block_id,
           dbms_rowid.rowid_row_number(rowid) num
      from t; ROWID               OBJECT_ID    FILE_ID   BLOCK_ID        NUM------------------ ---------- ---------- ---------- ----------AAAXUTAAGAAAEe9AAA      95507          6      18365          0 alter system dump datafile 6 block 18365; System altered
    data_block_dump,data header at 0xa768464===============tsiz: 0x1f98hsiz: 0x14pbl: 0x0a768464bdba: 0x018047bd     76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0x40avsp=0xfd8tosp=0xfd80xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0x40block_row_dump:tab 0, row 0, @0x40tl: 4012 fb: --H-F--- lb: 0x1  cc: 1nrid:  0x018047bc.0--链接的块的地址col  0: [4000] 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 ................................省略.....................................end_of_block_dump
    转换nrid:
    select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047bc',
                                                          'xxxxxxxxxx')) file#,
           dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047bc',
                                                           'xxxxxxxxxx')) block#
      from dual;  
     alter system dump datafile 6 block 18364;    System altered 
    链接块1data_block_dump,data header at 0xa76847c===============tsiz: 0x1f80hsiz: 0x14pbl: 0x0a76847cbdba: 0x018047bc     76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0x2eavsp=0xfc0tosp=0xfc00xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0x2eblock_row_dump:tab 0, row 0, @0x2etl: 4012 fb: -------- lb: 0x2  cc: 1nrid:  0x018047c0.0--链接的块的地址col  0: [4000] 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 ................................省略.....................................end_of_block_dump    SQL>select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047c0',                                                        'xxxxxxxxxx')) file#,         dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047c0',                                                         'xxxxxxxxxx')) block#    from dual;alter system dump datafile 6 block 18368; System altered  
     链接块2data_block_dump,data header at 0xa76847c===============tsiz: 0x1f80hsiz: 0x14pbl: 0x0a76847cbdba: 0x018047c0     76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0xfdaavsp=0xfc6tosp=0xfc60xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0xfdablock_row_dump:tab 0, row 0, @0xfdatl: 4006 fb: -----L-- lb: 0x3  cc: 1col  0: [4000] 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33................................省略.....................................end_of_block_dump
    实验一个行链接

    3.3小结:行迁移和行迁移的区别、危害            

    区别:可以看到行链接发生在update或insert,有一部分数据放在当前块,有一部分数据放在链接的块中。行迁移在当前块只放一个地址,内容全部在链接的块中,且可能有多个链接块。

    危害:会引起额外的I/O操作。

    3.4 如何检测出行迁移?

    @?RDBMSADMINutlchain.sql
    
    analyze table 【table_name】 list chained rows into chained_rows;
    
    select owner_name,table_name,head_rowid from chained_rows;
    检测行迁移行链接

    注意:如果要在正式环境上执行,不能在上班时间执行

    3.5 如何避免和消除行迁移和行链接

    •不要插入一行数据,而一行带有大量NULL的列,更合适的是,从一开始插入数据就要填满行。
    •使用增大block size的表空间。
    •增大pctfree。
    •重建表或索引。

        行链接和行迁移检测和消除方法:http://blog.csdn.net/guogang83/article/details/8671425

    4.高水位线含义及问题

    •ORACLE用HWM来界定一个段中使用的块和未使用的块。 HWM在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移。这就好比是水库的水位,当涨水时,水位往上移,当水退出后,最高水位的痕迹还是清淅可见。ORACLE的全表扫描是读取高水位标记(HWM)以下的所有块。
     
    •高水位线带来的问题:如果在执行删除操作后不降低高水位线标记,则将导致查询语句的性能低下。
    drop table test1 purge;
    create table test1 as select * from dba_objects;
    begin
      for i in 1 .. 100 loop
       execute immediate 'insert into test1 select * from dba_objects';
      end loop;
    end;
    exec dbms_stats.gather_table_stats(user,'TEST1');
    select count(*) from test1;
    delete from test1;
    select count(*) from test1;
    高水位

    4.1如何修正ORACLE表的高水位线

    •执行表重建指令 alter table table_name move;

    •执行alter table table_name shrink space; 注意,此命令为Oracle 10g新增功能,再执行该指令之前必须允许行移动alter table table_name enable row movement;
    •复制要保留的数据到临时表t,drop原表,然后rename临时表t为原表;
    •emp/imp;
    •alter   table  table_name  deallocate   unused ;
    •尽量truncate 。
     
    5.Drop、Truncate 和delete区别--语句类型上来区分
    •delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发。
    •truncate是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger。
    •Drop是ddl。

    DDL和DML区别:Metadata(元数据:数据仓库中非常重要的概念,管理数据的数据,oracle中的数据字典据都可以理解成元数据)。DDL就是操作元数据的操作,自动提交。

    5.1Truncate和drop的区别

      通过redo及执行时间:

     

    产生redo

    执行时间

    truncate

    53k

    00: 00: 01.06

    drop

    26k 

    00: 00: 00.28

      用10046跟踪truncate 和drop后台在做什么事情:

     

    update语句数量

    delete语句数量

    insert语句数量

    truncate

    7

    6

    1

    drop

    2

    45

    0

    实验5.1 Truncate 与Drop的产生的redo大小

    参照:http://blog.csdn.net/guogang83/article/details/8723582测量redo:

    create table test as select * from dba_objects;select  value  2   from v$mystat, v$statname  3  where v$mystat.statistic# =v$statname.statistic#  4     and v$statname.name ='redo size';      VALUE----------     94912 truncate table test; Table truncatedselect  value  2   from v$mystat, v$statname  3  where v$mystat.statistic# =v$statname.statistic#  4     and v$statname.name ='redo size';      VALUE----------    149588 select (149588-94912)/1024 from dual; (149588-94912)/1024-------------------        53.39453125 drop table test purge; Table dropped select  value  2   from v$mystat, v$statname  3  where v$mystat.statistic# =v$statname.statistic#  4     and v$statname.name ='redo size';      VALUE----------    168404 create table test as select * from dba_objects; Table created select  value  2   from v$mystat, v$statname  3  where v$mystat.statistic# =v$statname.statistic#  4     and v$statname.name ='redo size';      VALUE----------    263320 drop table test purge; Table dropped select  value  2   from v$mystat, v$statname  3  where v$mystat.statistic# =v$statname.statistic#  4     and v$statname.name ='redo size';      VALUE----------    290364 select (290364-263320)/1024 from dual; (290364-263320)/1024--------------------         26.41015625
    实验Truncate与Drop产生的Redo大小

    5.2Drop、Truncate 和delete区别--安全性考虑

    •如果没有备份,尽量不要用truncate。
    •想保留表而将所有数据删除。如果和事务无关,用truncate即可。如果和事务有关,或者想触发trigger,还是用delete。
    •想删除部分数据行用delete,注意带上where子句,回滚段要足够大。用delete误删数据后如何恢复。
    •SELECT count(*) from pub_department AS OF TIMESTAMP TO_TIMESTAMP('2012-08-26 15:29:00', 'YYYY-MM-DD HH24:MI:SS');

    select * from recyclebin;

    6.课后作业:

    1.Dump block,你所管理的表,给出内容解析;

    row#116[3356] flag: ---D--, lock: 2, len=40
    col 0; len 30; (30):
     42 49 4e 24 33 53 55 43 46 34 6d 43 52 4e 36 49 78 71 52 34 6d 62 65 64 5a
     51 3d 3d 24 30
    col 1; len 6; (6):  01 0c 9e 7c 00 2a

    -------以上为截取的一段Dump文件数据----
    col 0 表示数据
    col 1 表示rowid

    col 1; len 6; (6):  01 0c 9e 7c 00 2a

    16进制----》2进制 00000001  00001100  10011110  01111101  00000000  00101010

    转换为2进制后                                    二进制                                            十进制          十六进制
    前十位表示文件号                               0000000100          ---------------------->4       004
    中间22位表示块号                               0011001001111001111101 ----------->827005    0C9E7D 
    最后16位表示行号                               0000000000101010            ----------->42                  002A
     
    文件编号+块编号+行编号:=0040C9E7D002A
    数据对象编号        文件编号        块编号           行编号
    OOOOOO             FFF            BBBBBB            RRR
            004           0C9E7D          002A
     
    2.行链接的实验;
  • 相关阅读:
    mysql联合索引命中条件
    Shiro知识初探(更新中)
    Java中使用MongoTemplate进行分批处理数据
    Java中String时间范围比较
    使用ReentrantLock
    使用Condition
    python的坑--你知道吗?
    python基础--函数全解析(1)
    CSS基本语法及页面引用
    HTML学习汇总
  • 原文地址:https://www.cnblogs.com/HondaHsu/p/3530079.html
Copyright © 2011-2022 走看看