`
hanjian861202
  • 浏览: 159729 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

Oracle block的调优

阅读更多

1.如果一行的数据太大以至一个单独的block容纳不下,会产生两种现象:

  1)

      A、Chaining:插入新数据时,行数据太大以至一个空block容纳不下,oracle会将这一行的数据存放在一个或多个block 组成的block chain中,insert、update都可能导致这个问题,在某些情况下row chaining是不能避免的。

  B、Migration:修改数据时,可能导致行数据增大,以至它所在的block剩余空间容纳不下,oracle server会去寻找一个有足够自由空间容纳整行数据的block,如果这样的block存在,oracle server把整行移到新的block,在原位置保存一个指向新存放位置的镜像行,镜像行的rowid和原来的rowid一致。

      其实行迁移是行链接的一种特殊形式,但是它的起因与行为跟行链接有很大不同,所以一般把它从行链接中独立出来,单独进行处理。

  2) 行链接和行迁移引起数据库性能下降的原因:
引起性能下降的原因主要是由于引起多余的I/O造成的。当通过索引访问已有行迁移现象的行时,数据库必须扫描一个以上的数据块才能检索到改行的数据。这主要有一下两种表现形式:
    A 、导致row migration 或row chaining INSERT 或 UPDATE语句的性能较差,因为它们需要执行额外的处理
    B 、利用索引查询已经链接或迁移的行的select语句性能比较差,因为它们要执行额外的I/O

2.测试和检测migration和chaining:

      1)测试

     

create table test ( x int primary key, a char(2000), b char(2000), c char(2000), d char(2000), e char(2000) ) tablespace TS_TEST;

查看TS_TEST这个表空间的数据文件号

select file_id from dba_data_files where tablespace_name='TS_TEST';

数据库的db_block_size是8K,创建的表有五个字段,每个占2000个字节,这样一行记录大约10K,就能超过一个block的大小了。

insert into test(x) values (1);COMMIT;

查找这行记录所在的block,并dump出来

select dbms_rowid.rowid_block_number(rowid) from test;

alter system dump datafile 23 block 34;

在udump目录下查看trace文件的内容

update test set a='test',COMMIT;

alter system dump datafile 23 block 34;

trace文件的内容:nrid出现了值,指向了下一个row id,证明刚刚的update操作使这行记录产生了行链接或者行迁移了

      
      2)检测

       A、系统级别

       SELECT name, value FROM v$sysstat WHERE name = 'table fetch continued row';

       B、表级别
      Analyize table table_name compute statistics;

  Select num_rows,chain_cnt from dba_tables where table_name=’...’;

   C、记录级别  

     @?/rdbms/admin/utlchain.sql
       ANALYZE TABLE table_name LIST CHAINED ROWS;
       select owner_name,table_name,head_rowid from chained_rows

 

3.解决方法:

     防范于未然:

     1)行链接

     在大多数情况下,行链接是无法克服的,特别是在一个表包含象LONGS, LOBs 等这样的列时。当在不同的表中有大量的链接行,并且哪些表的行的长度不是很长时,你可以通过用更大的block size重建数据库的方法来解决它或者修改表的结构。
      例如:当前你的数据库的数据块的大小为4K,但是你的行的平均长度为6k,那么你可以通过用8k大小的数据块来重建数据库的办法解决行链接现象。

     2)行迁移
      产生Migration的原因可能是由于PCTFREE设置的太低以至没有保留足够的空间用于更新,可以通过增加PCTFREE的值避免行镜像产生。但这种解决办法是以牺牲更多的空间为代价的,这也就是我们通常所说的以空间换效率。而且通过增加PCTFREE值的办法只能缓解行迁移现象,而不能完全解决行迁移,所以较好的办法是在设置了合适的PCTFREE值的后,在发现行迁移现象比较严重时,对表的数据进行重组。
   

   亡羊补牢:

     3)表重组   

     若某张表迁移现象严重,可考虑对表进行重组,即使用export+truncate/drop原表+import或者把表移入另一个表空间(alrer table table_name move tablespace_name);注意移动表时,要考虑表上的约束和索引等。

     4)记录重组

  运行analyize table ... list chained rows;

  复制镜像行到另一个表tmp;

  从源表中删除这些行;

  从tmp中将这些行插回到源表中。

  脚本:

  /* 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

  set echo on

  spool fix_mig

  /* List the chained & 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

  使用这个脚本时,必须将涉及到的外键约束去掉。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics