我们的数据库的行连接已经到了一个比较严重的地步了,对awr 报表的统计数据是 sunha5 花在行连接的 i/o 是平均每秒 600 次左右。 通过对产品库和商家进行清理后,目前的统计降到了200 次左右,还有继续下降的空间。 行连接的成因 : 行连接(chained rows) 是因为对字段做修改后,导致修改后的数据大于原来的数据长度,在现在的行里,已经无法存储这个数据,写不下的数据会被放到别的数据块里,并且在原行中纪录这个地址。这样导致的问题是,如果要读出这个行数据, oracle 必须要进行 2 次甚至多次 i/o 操作才会把整行数据读出来,增加了 i/o 成本,导致性能下降。 Oracle 提供了工具进行行连接的检测: 我们以商家系统的处理为例演示下: 注: 本操作为直接修改线上数据库需要小心执行。 1. 在当前用户下执行 $ORACLE_HOME/rdbms/amdin/utlchain.sql 建立一个表。
键表语句:
create table CHAINED_ROWS (
owner_name varchar2(30),
table_name varchar2(30),
cluster_name varchar2(30),
partition_name varchar2(30),
subpartition_name varchar2(30),
head_rowid rowid,
analyze_timestamp date
);
2. 对要进行分析的表执行分析命令:
analyze table table_name list chained rows into CHAINED_ROWS;
select 'analyze table cyp_app.'||table_name||' list chained rows into CHAINED_ROWS;' from dba_tables where owNer='CYP_APP';
生成商家的所有的表的分析语句然后批量执行。
这个分析命令会把表中有行连接的行的rowid 纪录到这个表中。
Select * from chained_rows:
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM5yAAJ 07-1 月 -09
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM51AAU 07-1 月 -09
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM53AAK 07-1 月 -09
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM54AAF 07-1 月 -09
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM56AAG 07-1 月 -09
CYP_APP ENT_COMPANY_TEXT N/A AABZKnABNAAAM6AAAH 07-1 月 -09
3. 处理行连接的数据。先备份 ,删除原表的数据,然后再insert
drop table tmp_as;
-- 建立临时表。
create table tmp_as as select a.* from CYP_APP.ENT_QUESTION a where a.rowid in (
select head_rowid from chained_rows where table_name ='ENT_QUESTION');
select * from tmp_as ;
4. 对表进行更新,删除和insert 操作尽量争取在一个事务里完成。如果有外键引用需要先把外键引用禁用掉。
Commit;
delete from CYP_APP.ENT_QUESTION where rowid in (
select head_rowid from chained_rows where table_name ='ENT_QUESTION');
insert into CYP_APP.ENT_QUESTION select * from tmp_as ;
Commit;
5. 从 chained_rows 表中删除跟该表相关的纪录
delete from chained_rows where table_name ='ENT_QUESTION';
6. 如果表的 chained rows 比较多,比如有几万笔纪录或者 10 几万笔纪录,
我们因该考虑修改表的存储参数,把pctfree 参数修改为 15 或者 20
alter table CYP_APP.ENT_QUESTION pctfree 15 ;
7, 如果表的行连接比较多,到了几万笔的数量级,那么对这个表的 update 说明已经进行了很多次的了,
索引估计也会比较大,浪费空间。建议对该表的索引做一个rebuild
