zoukankan      html  css  js  c++  java
  • 行迁移和行链接

    1.行迁移

    什么是行迁移

    当一个行上发生更新操作,更新后当前数据块无法容纳改行数据,该行数据就会整体迁移到其他数据块中,原来行所在位置仅仅保留一个地址,指向改行所在的位置
    

    行迁移带来的性能问题

    通过索引扫描进行回表操作时,原本读到本块地址就会返回数据库。但是发生行迁移之后,读到本行数据列发现仅仅有一个地址指针,需要再多访问一个数据页。
    这样使用索引扫描进行检索数据就会比之前要多扫描一个数据块,如果数据量较大情况下,可能就会带来性能上的问题
    

    检查行迁移

    @?/rdbms/admin/utlchain.sql --执行该sql会在当前用户下创建一个CHAINED_ROWS表
    analyze table table_name list chained rows into chained_rows; --执行该命令会将行迁移的表插入到CHAINED_ROWS表中

    预防与解决办法

    1.创建表结构的时候调整pctfree大小,将这个值调大
    2.碎片整理,通过alter table xxx move或通过中间表方式

    --通过创建中间表的方式解决行迁移
    create table EMPLOYEES_TMP as select * from EMPLOYEES where rowid in (select head_rowid from chained_rows);
    Delete from EMPLOYEES where rowid in (select head_rowid from chained_rows);
    Insert into EMPLOYEES select * from EMPLOYEES_TMP;
    delete from chained_rows ;
    commit;
    

    验证发生行迁移后索引扫描操作会增加一个buffer

    创建测试表并创建索引
    drop table EMPLOYEES purge;
    CREATE TABLE EMPLOYEES AS SELECT * FROM HR.EMPLOYEES ;
    create index idx_emp_id on employees(employee_id);
    
    收集统计信息
    exec dbms_stats.gather_table_stats('dbmon','employees',cascade=>true,no_invalidate=>false);
    
    创建chained_rows,为检查检查行迁移做准备
    @?/rdbms/admin/utlchain.sql
    analyze table EMPLOYEES list chained rows into chained_rows;
    --检查发现改表没有行迁移发生
    SQL> select count(*) from chained_rows;
    
      COUNT(*)
    ----------
             0
    
    
    --查看执行计划,从下面执行计划可以看出,索引扫描耗费了2个buffer,回表时,又增加了一个buffer,一共消耗了3个buffer
    select LAST_NAME,FIRST_NAME from employees where employee_id=149
    
    Plan hash value: 2126936620
    
    ------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
    ------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |            |      1 |        |       |     2 (100)|          |      1 |00:00:00.01 |       3 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES  |      1 |      1 |    19 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |
    |*  2 |   INDEX RANGE SCAN          | IDX_EMP_ID |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
    ------------------------------------------------------------------------------------------------------------------------------------
    
    --执行如下操作后,验证employees是否存在行迁移
    alter table EMPLOYEES modify FIRST_NAME VARCHAR2(1000);
    alter table EMPLOYEES modify LAST_NAME  VARCHAR2(1000);
    alter table EMPLOYEES modify EMAIL VARCHAR2(1000);
    alter table EMPLOYEES modify PHONE_NUMBER  VARCHAR2(1000);
    
    UPDATE EMPLOYEES
    SET FIRST_NAME = LPAD('1', 1000, '*'), LAST_NAME = LPAD('1', 1000, '*'), EMAIL = LPAD('1', 1000, '*'),
    PHONE_NUMBER = LPAD('1', 1000, '*');
    
    --验证行迁移,从如下查询,可以得到确是发生了行迁移,有107行
    @?/rdbms/admin/utlchain.sql
    analyze table EMPLOYEES list chained rows into chained_rows;
    --检查发现改表没有行迁移发生
    SQL> select count(*) from chained_rows;
    
      COUNT(*)
    ----------
          107
    
    --再次执行SQL,查看执行计划,这里索引消耗了2个buffer,回表时消耗了2个buffer,一共四个buffer,验证之前解释行所在位置仅仅保留一个地址,指向改行所在的位置(这里多一个buffer)
    
    select LAST_NAME,FIRST_NAME from employees where employee_id=149
    
    Plan hash value: 2126936620
    
    ------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
    ------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |            |      1 |        |       |     2 (100)|          |      1 |00:00:00.01 |       4 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES  |      1 |      1 |    19 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |
    |*  2 |   INDEX RANGE SCAN          | IDX_EMP_ID |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
    ------------------------------------------------------------------------------------------------------------------------------------
    

    2.行链接

    什么是行链接

    当某行数据量太大,一个block无法存放,就会发生行链接(一行数据存放在多个数据块中),这种情况无法避免
    

    检查行链接

    analyze table 表名 validate structure cascade into chained_rows;

  • 相关阅读:
    linux包之coreutils之du和df命令
    java实现第六届蓝桥杯加法变乘法
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯打印大X
    java实现第六届蓝桥杯移动距离
    java实现第六届蓝桥杯移动距离
    java实现第六届蓝桥杯循环节长度
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯格子中输出
  • 原文地址:https://www.cnblogs.com/hanglinux/p/15244093.html
Copyright © 2011-2022 走看看