处理行链接

来源:互联网 发布:linux分区方案 知乎 编辑:程序博客网 时间:2024/04/30 08:54
问题描述:
你有一张表,其中的数据行可能存储在多个数据块中,这回增加IO使用率,减慢查询速度,你想使这些数据位于一个数据块中

当表有显著的行链接问题时,手工执行段顾问建议,可得到以下输出
select
 'TASK_NAME      :'||T1.TASK_NAME ||CHR(10)||
 'START_RUN_TIME :'||TO_CHAR(T1.EXECUTION_START,'YYYY-MM-DD HH24:MI:SS') ||CHR(10)||
 'SEGMENT_OWNER  :'||T3.ATTR1 ||CHR(10)||
 'SEGMENT_NAME   :'||T3.ATTR2 ||CHR(10)||
 'PARTITION_NAME :'||T3.ATTR3 ||CHR(10)||
 'SEGMENT_TYPE   :'||T3.TYPE  ||CHR(10)||
 'MESSAGE        :'||T2.MESSAGE||CHR(10)||
 'MORE INFO      :'||T2.MORE_INFO||CHR(10)||
 '---------------------------------' ADVICE
  from dba_advisor_executions t1,
       dba_advisor_findings   t2,
       dba_advisor_objects    t3
 where t1.task_id = t2.task_id
   and t2.task_id = t3.task_id
   and t2.object_id=t3.object_id
   and t1.advisor_name = 'Segment Advisor'
   and t1.execution_last_modified > sysdate - 1
   and t2.type = 'PROBLEM'
   and t2.task_name='TEST ADVISOR';

ADVICE
--------------------------------------------------------------------------------
TASK_NAME      :TEST ADVISOR
START_RUN_TIME :2016-09-13 11:25:31
SEGMENT_OWNER  :SCOTT
SEGMENT_NAME   :TEST
PARTITION_NAME :
SEGMENT_TYPE   :TABLE
MESSAGE        :The object has chained rows that can be removed by re-org.
MORE INFO      :58 percent chained rows can be removed by re-org.
---------------------------------

从上面的输出可以看出,TEST表有58%的行有行链接问题,通过

解决方案:
1、使用move,会对表加排它锁,并且会使索引失效(因为会重新分配rowid)
alter table test move;
select owner,index_name,status from dba_indexes where table_name='TEST';
alter index xxx rebuild;

工作原理:
每个数据块会保留一定空间,用于行增长。如果剩余空间不够容纳数据的增长,oracle就会创建一个指针指向另外一个数据块,共同存储一行数据。当一行数据存储在两个或多个数据块中,成为行链接。这会导致读取一行数据需要访问两个数据块,导致潜在的性能问题

一般如果表中有15%的行有行链接,则需要处理

块中保留的空闲存储空间有pctfree决定,默认10%。如果表中某列初始插入null值,之后更新为较大的值,可以考虑增大pctfree的值。
select table_name,pctfree from user_tables

move操作会清楚数据块的记录,然后重新插入,链接行被删除并重新组织,可改变pctfree
alter table test move pctfree 40

处理行链接的第二种方法:analyze table
@?/rdbms/admin/utlchain.sql
创建名为chained_rows的表,使用analyze命令
analyze table test list chained rows;
查询chained_rows表中的数据行数
select count(*) from chained_rows where table_name='TEST';
返回0行说明没有行链接,接下来处理行链接:
1、创建临时存储链接行的表
2、从原始表中删除链接的行
3、将临时表中的行插入到原始表中,删除临时表

create table test_tmp as select * from test where rowid in(select head_rowid from chained_rows where table_name='TEST' and owner_name='SCOTT');
delete from test where rowid in (select head_rowid from chained_rows where table_name='TEST' and owner_name='SCOTT');
insert into test select * from test_tmp;
drop table test_tmp purge;

重新分析这张表,行链接已消除

理解rowid:
每一行数据都有一个物理地址。由以下因素共同确定
1、数据文件编号
2、数据块编号
3、行在块中的位置
4、对象编号
select rowid,empno from emp;

rowid不存储在数据库中,oracle会在查询中计算它的值,rowid包含A-Z,a-z,0-9,+以及/。可通过dbms_rowid翻译这些信息。

select empno,rowid,dbms_rowid.ROWID_RELATIVE_FNO(rowid),

 dbms_rowid.ROWID_BLOCK_NUMBER(rowid),dbms_rowid.ROWID_ROW_NUMBER(rowid) from emp;


rowid可以使用在select和update等语句中,一般情况rowid是唯一的,但如果是聚簇,则可能多行数据有相同rowid


另外导出,导入也可消除行链接

0 0
原创粉丝点击