行链接(Row chaining) 与行迁移(Row Migration)

来源:互联网 发布:vb会动的文字代码 编辑:程序博客网 时间:2024/05/16 05:09

当一行的数据过长而不能插入一个单个数据块中时,可能发生两种事情:行链接(row chaining)或行迁移(row migration)。

行迁移:  当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移。一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址。因此整行数据都被                 移动,原始的数据块上仅仅保留的是指向新块的一个地址信息。
                产生:update
行链接:  当一行数据太大而不能在一个单数据块容纳时,行链接由此产生。举例来说,当你使用了4kb的Oracle 数据块大小,而你需要插入一行数据是8k,Oracle则需要使用3个数据块分成片来存储。因此,引                起行链接的情形通常是,表上行记录的大小超出了数据库Oracle块的大小。
           产生:insert
           表上使用了LONG 或 LONG RAW数据类型的时候容易产生行链接。其次表上多于255列时Oracle会将这些过宽的表分片而产生行链接

迁移行对索引读产生额外的I/O,对全表扫描没什么影响
行链接则影响索引读和全表扫描行额外的处理


2) 利用索引查询已经链接或迁移的行的select语句性能比较差,因为它们要执行额外的I/O
http://www.itpub.net/thread-1618576-1-1.html

行迁移主要是由于设置的PCTFREE参数过小,导致没有给update操作留下足够的空闲空间引起。为了避免行迁移,所有被修改的表应该设置合适的PCTFREE 值,以便在每个数据块内为数据修改保留足够的空间。可以通过增加PCTFREE值的办法来避免行迁移,但这种解决办法是以牺牲更多的空间为代价的,这也就是我们通常所说的以空间换效率。 而且通过增加PCTFREE值的办法只能缓解行迁移现象,而不能完全解决行迁移,所以较好的办法是在设置了合适的PCTFREE值的后,在发现行迁移现象比较严重时,对表的数据进行重组。下面是对行迁移数据进行重组的步骤(这种方法也被成为CTAS):
PS: 

PCTFREE: 数据块的可用空间低于多少的时候,不能再insert,只能update

PCTUSED: 数据块的数据低于多少的时候,可以再insert。


http://www.cnblogs.com/linjiqin/archive/2012/01/16/2323320.html


二、如何检测出来行迁移或者行链接:


1.创建chained rows需要的表:
sql> @/home/oracle/product/10.xx/rdbms/admin/utlchain.sql


2.将表中的chained row移动到chained_rows表
SQL> analyze table test_table_name list chained rows;
SQL> SELECT * FROM chained_rows;


或者:
当然你也可以通过检查v$sysstat视图中的'table fetch continued row'来检查被迁移或被链接的行。


SQL> SELECT name, value FROM v$sysstat WHERE name = 'table fetch continued row';
NAME VALUE
---------------------------------------------------------------- ---------
table fetch continued row 308


三、解决方法


analyze table 之后:
select table_name,num_rows,CHAIN_CNT from user_tables ; 
or
select table_name,num_rows,CHAIN_CNT from dba_tables where owner='XXXXXXX' ;
方法1:直接truncate表,然后再导入导出 datapump,但这样downtime比较长,而且如果有外键约束之类的,比较麻烦。

方法2:alter table move,然后rebuild index
analyze table t compute statistics

举例:
SQL> alter table t add t1 date default sysdate; 
Table altered. 


SQL> c/t1/t2 
  1* alter table t add t2 date default sysdate 
SQL> / 
Table altered. 
   
SQL> c/t2/t3 
    1* alter table t add t3 date default sysdate 
SQL> / 
Table altered. 
   
SQL> analyze table t compute statistics; 
Table analyzed. 


SQL> select table_name,num_rows,CHAIN_CNT from user_tables where table_name='T'; 
   
TABLE_NAME            NUM_ROWS CHAIN_CNT 
------------------------------ ---------- ---------- 
T                  41616    3908 
   
SQL> alter table t move ; 
Table altered. 
   
SQL> analyze table t compute statistics; 
Table analyzed. 


SQL>select table_name,num_rows,CHAIN_CNT from user_tables where table_name='T'; 
TABLE_NAME            NUM_ROWS CHAIN_CNT 
------------------------------ ---------- ---------- 
T                  41616     0
rebuild index




方法3: 通过数据字典来chained_ROWS,然后analyze table XX LIST chained ROWS;创建中间表,查出并迁移行。
参考http://blog.csdn.net/hotye393/article/details/6226471


-- Get the name of the table with migrated rows:
ACCEPT table_name PROMPT 'Enter the name of the table with migrated rows: '


-- Clean up from last execution
set echo off
DROP TABLE migrated_rows;
DROP TABLE chained_rows;


-- Create the CHAINED_ROWS table
@.../rdbms/admin/utlchain.sql
set echo on
spool fix_mig
-- List the chained and migrated rows
ANALYZE TABLE &table_name LIST CHAINED ROWS;


-- Copy the chained/migrated rows to another table
create table migrated_rows as
SELECT orig.*
FROM &table_name orig, chained_rows cr
WHERE orig.rowid = cr.head_rowid
AND cr.table_name = upper('&table_name');


-- Delete the chained/migrated rows from the original table
DELETE FROM &table_name WHERE rowid IN (SELECT head_rowid FROM chained_rows);


-- Copy the chained/migrated rows back into the original table
INSERT INTO &table_name SELECT * FROM migrated_rows;


spool off

但是如果chained_rows本身就存在链接行,那么只能改变block 的大小来解决了。

四、数据块大小的选择标准:
小的:


行的宽度很小,并伴有大量的随机访问(Random Access)
减少块竞争
注:选择小尺寸数据块会浪费大量的存储空间,

大的:

行的宽度很大,或者含有LOB字段
应用中存在大量的顺序读(Sequential Access)
节省I/O,一次可以读入更多的数据量
节省存储空间










原创粉丝点击