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;

  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/hanglinux/p/15244093.html
Copyright © 2011-2022 走看看