行迁移、行链接

实验目的:了解、查询、处理行迁移、行链接的情况

 

1..解释说明:块、行迁移、行链接、视图、analyze命令、查询

 

2,0实验思路:

2.1:行链接

2.2:测试出一个行链接的数据

2.3:发生行链接,有什么好的方法

 

2.4:行迁移

2.5:测试出一个行迁移的数据

2.6:发生行迁移,有什么好的方法

 

 

 

1.解释说明:块、行迁移、行链接、视图、analyze命令、查询

 

1.1:块的空间说明:

块:分三个区域:块头部、可用空间、预留空间

==>1.1.1.block header  【 ITL事物槽:记录在block上transaction 的相关记录
                                        undo block: 记录undo block地址信息
                                        table directory 记录表的信息
                                        row directory     记录行的信息】
 
==>1.1.2 available space 【有效可用空间:insert】
 
==>1.1.3 free space 【通过设置pctfree 当块空间使用率达到xx%时,不允许insert
                                    预留空间update操作】
           
                                  
1.2:行迁移:
                    =>Update操作时,如果free space的空闲空间,无法存储被Update更新后的rows,将会产生行迁移:整行记录迁移至另一个块中
                    =>当通过索引访问时,通过键值,找到rowid,rowid没有发生改变,导致索引访问通过rowid访问发现行已经迁移走了,之前访问一个块可以找到数据,如今需要两个。
 
 
1.3行链接:
                  =>Insert操作时,如果Blocks中的free space不足以存储整行记录,此时,ROW会将一部分的字段存储在另一个块中
                  =>通过索引访问,会增加至少一次IO的访问
 
 
1.4:记录表:行迁移、行链接的rowid信息都会在此视图中记录:
#默认:没有此对象: 
select * from chained_rows;
ERROR at line 1: ORA-00942: table or view does not exist
 
#执行脚本:创建:行迁移、行链接:记录表
SQL>@?/rdbms/admin/utlchain.sql

#视图结构信息:
SQL> desc chained_rows; Name Null? Type ----------------------------------------- -------- ---------------------------- OWNER_NAME 表的用户
TABLE_NAME 表名称 CLUSTER_NAME PARTITION_NAME 分区名称 SUBPARTITION_NAME 子分区名称 HEAD_ROWID 链接行 rowid ANALYZE_TIMESTAMP 使用analyze分析时间


SQL> select OWNER,OBJECT_NAME,OBJECT_TYPE from dba_objects where owner='SYS'
and object_name='CHAINED_ROWS';

OWNER OBJECT_NAME OBJECT_TYPE
-----------------------------------------------------------------------------
SYS CHAINED_ROWS TABLE


1.5:analyze 收集表结构统计信息:

未收集user_tables很多信息缺失,无法查询

  命令: analyze table xx compute statistics;

  命令: analyze table xx LIST CHAINED ROWS INTO chained_rows;

 
 
 

2,0实验思路:

 

2.1:测试出一个行迁移的数据

2.2:行迁移带来的问题:

2.3:发生行迁移,有什么好的方法

 

2.4:测试出一个行链接的数据

2.2:行链接带来的问题:

2.3:发生行链接,有什么好的方法

 

 

 

             
2.1模拟测试出一个行迁移:
         
 
#创建一个对象表:
SQL> create table row_a(id char(1500),name char(2000),city varchar2(2000));

#Insert测试数据:两行数据:7000多个字节

SQL> insert into row_a values(1,'yang','beijing');

SQL> insert into row_a values(2,'cheng','hukou');

SQL> commit;

#收集表的结构信息
SQL> analyze table row_a compute statistics;


#查询表的平均行长度

SQL> select table_name,avg_row_len from user_tables where table_name='ROW_A';

TABLE_NAME                     AVG_ROW_LEN

------------------------------ -----------

ROW_A                                 3516

 

#查询表的rowid

SQL> select rowid from row_a order by 1;

ROWID

------------------

AAADzKAAFAAAADsAAA

AAADzKAAFAAAADsAAB

 

#第一次Update

 SQL> update row_a set city=(select name from row_a where id=2) where id=2;

#分析

SQL> analyze table song.row_a list chained rows;

#ROWID不变:

SQL> select rowid from row_a order by 1;

AAADzKAAFAAAADsAAA

AAADzKAAFAAAADsAAB

#查询视图:未发现记录

select * from chained_rows

no rows selected

 

#第二次UPDATE

 SQL> update row_a set city=(select name from row_a where id=2) where id=1;
SQL> commit;

 

#ROWID不变:

SQL> select rowid from row_a order by 1;

AAADzKAAFAAAADsAAA

AAADzKAAFAAAADsAAB

 

#查询视图:第二行数据:发生了行迁移

select * from chained_rows

SONG           ROW_A     N/A          AAADzKAAFAAAADsAAB 07-APR-18

 

 2.2:使用set autotrace 工具:
 

#通过Rowid查询:都在一个块中

select rowid from row_a

ROWID

------------------

AAADzKAAFAAAADsAAA

AAADzKAAFAAAADsAAB


#查询结果7次逻辑读:读取这两行记录:读取了两个块,原本只需要一个块,会最少多一次逻辑读
SQL> set autotrace traceonly; SQL> select * from row_a; 7 consistent gets


#此处有系统的调用,为了更好的对比此次实验:
创建一个新表,一条数据,查询对比
create table c(id int);
insert into c(1);
commit;
SQL> analyze table c compute statistics;
set autotrace traceonly;
select * from c;
          6  consistent gets

 

2.3:发生了行迁移:如何更好的处理:

=> 修改Block中的Pctfree值,设置减少,增加块中预留update的空间

 

SQL> select table_name,PCT_FREE from user_tables where table_name='ROW_A';

TABLE_NAME                       PCT_FREE
------------------------------ ----------
ROW_A                                  10


SQL> alter table row_a pctfree 20;

Table altered.

SQL> select table_name,PCT_FREE from user_tables where table_name='ROW_A';

TABLE_NAME                       PCT_FREE
------------------------------ ----------
ROW_A                                  20


#以上是为了如何避免:
#以下是如何解决此次:
SQL> alter table row_a move;
#通过rowid可以判断,两行数据,使用的不同的块
SQL> select rowid from row_a;

ROWID
------------------
AAADzNAAFAAAADrAAA  
AAADzNAAFAAAADsAAA

#查询视图: 记录还保留:问题其实已经解决
SQL> select * from chained_rows;

SONG                           ROW_A
N/A                            AAADzKAAFAAAADsAAB 07-APR-18

 

 

 

 

 

 

 

2.4:测试出一个行链接的数据

SQL> create table t_row_chaining(a char(2000),b char(2000),c char(2000),d char(2000));

SQL> insert into t_row_chaining values('x','y','z','a');

SQL> commit;

#分析表:将行链接、行迁移记录插入 chainde_rows
SQL> analyze table song.t_row_chaining list chained rows into chained_rows;

SQL> select * from chained_rows;

SONG                           T_ROW_CHAINING

N/A                            AAADzOAAFAAAAD9AAA 07-APR-18


 

 

2.5:行链接可能带来的性能问题:

#通过Rowid查询:都在一个块中

select rowid from T_ROW_CHAINING;

ROWID

------------------

AAADzOAAFAAAAD9AAA

SQL> set autotrace traceonly

SQL> select * from T_ROW_CHAINING;

          8  consistent gets    #至少多读一个块




#此处有系统的调用,为了更好的对比此次实验:
创建一个新表,一条数据,查询对比
create table c(id int);
insert into c(1); commit;
SQL> analyze table c compute statistics;
set autotrace traceonly;
select * from c;          
6  consistent gets

 

2.6:发生行链接,有什么好的方法

  =>使用非标准:大的数据块的数据文件:对应缓冲区,也需要有足够的buffer_size与之对应

#创建一个16K块大小的表空间
SQL> create tablespace block_16 datafile '/picclife/app/oracle/oradata/dingding/bk16.dbf' size 20m blocksize 16k;
#指定cache缓冲区:非标准块大小
SQL> alter system set db_16k_cache_size=20m;


 =>MOVE移动表到大块的表空间内
【如果不使用大块表空间存储,即使Move,由于单行数据大于一个块的存储还是会发生行链接】 alter table song.t_row_chaining move tablespace block_16; 分析: analyze table song.t_row_chaining list chained rows; #再次查询:ROWID发生改变 SQL
> select rowid from song.t_row_chaining; ROWID ------------------ AAADzSAAGAAAABDAAA #查询表中的ROWID在:行迁移、行链接中的 数据 SQL> select * from chained_rows where HEAD_ROWID=(select rowid from song.t_row_chaining); no rows selected

 

posted @ 2018-04-19 18:30  绿茶有点甜  阅读(343)  评论(0编辑  收藏  举报