行链接、行迁移:
行链接(Row Chaining):行链接产生在第一次插入数据的时候如果一个block不能存放一行记录的情况下。这种情况下,Oracle将使用链接一个或者多个在这个段中保留的 block存储这一行记录,行链接比较容易发生在比较大的行上,例如行上有LONG、LONG RAW、LOB等数据类型的字段,这种时候行链接是不可避免的会产生的,也就是说行链接发生在INSERT阶段数据块无法容纳过大数据时。
行迁移(Row Migrating):当一行记录初始插入的时候事可以存储在一个block中的,由于更新操作导致行长增加了,而block的自由空间已经完全满了,这个时候就产生了行迁移。在这种情况下,Oracle将会迁移整行数据到一个新的block中(假设一个block中可以存储下整行数据),Oracle会保留被迁移行的原始指针指向新的存放行数据的block,这就意味着被迁移行的ROW ID是不会改变的。也就是说行迁移发生在UPDATE阶段时原数据块无法容纳增大的数据时。因为在这种情况下查询需要扫描更多的数据块才能得到所需的信息,所以行链接和行迁移会导致系统的查询效率降低。
1.1. 行链接、行迁移测试
例1:测试行链接
第一步:建测试表(char类型,在块中固定占有空间,定长)
SYS@ORA11GR2>create table t_row_changing (x char(2000),y char(2000),z char(2000),q char(2000));
Table created.
第二步:插入初始化数据
SYS@ORA11GR2>insert into t_row_changing values('a','b','c','d');
1 row created.
SYS@ORA11GR2>commit;
Commit complete.
第三步:使用analyze命令对表t_row_chaining进行分析,以便验证该表是否发生了行链接。
SYS@ORA11GR2>analyze table t_row_changing list chained rows;
analyze table t_row_changing list chained rows
*
ERROR at line 1:
ORA-01495: specified chain row table not found
注:此时会出错,原因是CHAINED_ROWS表没有创建导致的!!!
第四步:使用Oracle自带的utlchain.sql脚本创建CHAINED_ROWS表,并再次分析表
SYS@ORA11GR2>@?/rdbms/admin/utlchain.sql
Table created.
SYS@ORA11GR2>analyze table t_row_changing list chained rows;
Table analyzed.
第五步:测试行链接,由于初始化的数据无法在一个数据块中存放(因为测试表所有字段都为char类型所致),此时发生了行链接。
SYS@ORA11GR2>col owner_name for a5
SYS@ORA11GR2>col table_name for a15
SYS@ORA11GR2>select owner_name,table_name,head_rowid,analyze_timestamp from chained_rows;
OWNER TABLE_NAME HEAD_ROWID ANALYZE_TIMESTAMP
----- --------------- ------------------ -------------------
SYS T_ROW_CHANGING AAAVuqAABAAAXLyAAA 2016-10-13 22:35:31
注:chained_rows表中,存在T_ROW_CHAINING的数据,即说明发生了行链接
例2:测试行迁移
第一步:建测试表(字段类型为varchar2,可变长)
SYS@ORA11GR2>create table t_row_migrating (x varchar2(2000),y varchar2(2000),z varchar2(2000),q varchar2(2000));
Table created.
第二步:插入初始化数据
SYS@ORA11GR2>insert into t_row_migrating values('a','b','c','d');
1 row created.
SYS@ORA11GR2>commit;
Commit complete.
第三步:此时由于是VARCHAR2类型的字段(此类型字段可以自适应数据的长短),此时数据完全可以在一个数据块中存放,因此此时不会发生行链接。分析表t_row_migrating,并验证是否存在行链接。
SYS@ORA11GR2>analyze table t_row_migrating list chained rows;
Table analyzed.
SYS@ORA11GR2>select owner_name,table_name,head_rowid,analyze_timestamp from chained_rows;
OWNER TABLE_NAME HEAD_ROWID ANALYZE_TIMESTAMP
----- --------------- ------------------ -------------------
SYS T_ROW_CHANGING AAAVuqAABAAAXLyAAA 2016-10-13 22:35:31
注:此时chained_rows表中,还是刚才我们测试行链接的那条记录。
第四步:我们使用t_row_chaining中的大数据对表t_row_migrating进行更新,使之发生行迁移。
SYS@ORA11GR2>update t_row_migrating set (x,y,z,q)=(select * from t_row_changing);
1 row updated.
SYS@ORA11GR2>commit;
Commit complete.
第五步:对表t_row_migrating进行分析,并验证行链接
SYS@ORA11GR2>analyze table t_row_migrating list chained rows;
Table analyzed.
SYS@ORA11GR2>select owner_name,table_name,head_rowid,analyze_timestamp from chained_rows;
OWNER TABLE_NAME HEAD_ROWID ANALYZE_TIMESTAMP
----- --------------- ------------------ -------------------
SYS T_ROW_CHANGING AAAVuqAABAAAXLyAAA 2016-10-13 22:35:31
SYS T_ROW_MIGRATING AAAVusAABAAAXkBAAA 2016-10-13 22:47:03
此时,我们发现表t_row_migrating已经存在chained_rows表中,注:chained_rows表中的数据,要么是出现了行迁移,要么就出现了行链接。
OWNER_NAME:表所属的schema
TABLE_NAME:表名
HEAD_ROWID:出现行迁移、行链接的rowid
ANALYZE_TIMESTAMP:执行ANALYZE的时间戳