`

Oracle行迁移和行链接详解(原创)

 
阅读更多

行迁移
成 因:当发出update导致记录行长增加,block的剩余空间不足以存放这条记录,就会产生行迁移,发生行迁移时rowid不会改变,原来的block 中会用一个指针存放这条记录在新的block中的地址,发生行迁移会对性能产生影响,因为读这条记录会读两个BLOCK。
后果:导致应用需要访问更多的数据块,性能下降。
预防:1. 将数据块的PCTFREE调大;2. 针对表空间扩大数据块大小
检查:analyze table 表名 validate structure cascade into chained_rows;
操作:(以EMPLOYEES_TEMP表为例,如果涉及到该表有主键,并且有别的表的外键REFERENCE关联到本表,必须要执行步骤2和步骤7,否则不必执行):
1.   执行$ORACLE_HOME/rdbms/admin目录下的utlchain.sql脚本创建chained_rows表。
2.   禁用所有其它表上关联到此表上的所有限制(假想EMPLOYEES_TEMP表有主键PK_EMPLOYEES_TEMP_ID,假想test表有外键f_EMPLOYEES_TEMP_id关联reference到EMPLOYEES_TEMP表)。
  select index_name,index_type,table_name from user_indexes where table_name='EMPLOYEES_TEMP';
  select  CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME from USER_CONSTRAINTS where R_CONSTRAINT_NAME='PK_EMPLOYEES_TEMP_ID';
  alter table test disable constraint f_EMPLOYEES_TEMP_id;
3.  将存在有行迁移的表(用table_name代替)中的产生行迁移的行的rowid放入到chained_rows表中。
4.  将表中的行迁移的row id放入临时表中保存。
5.  删除原来表中存在的行迁移的记录行。
6.  从临时表中取出并重新插入那些被删除了的数据到原来的表中,并删除临时表。
7.  启用所有其它表上关联到此表上的所有限制。
     alter table test enable constraint f_EMPLOYEES_TEMP_id;
注意:此外还可以采用move和exp/imp的方式(特别注意move会导致索引失效,需要重建索引)。
行迁移实验
--- PCTFREE试验准备之建表
DROP TABLE EMPLOYEES_TEMP PURGE;
CREATE TABLE EMPLOYEES_TEMP AS SELECT * FROM HR.EMPLOYEES ;
desc EMPLOYEES_TEMP;
create index idx_emp_id on EMPLOYEES_TEMP(employee_id);
--- PCTFREE试验准备之扩大字段
alter table EMPLOYEES_TEMP modify FIRST_NAME VARCHAR2(1000);
alter table EMPLOYEES_TEMP modify LAST_NAME  VARCHAR2(1000);
alter table EMPLOYEES_TEMP modify EMAIL VARCHAR2(1000);
alter table EMPLOYEES_TEMP modify PHONE_NUMBER  VARCHAR2(1000);
--- PCTFREE试验准备之更新表
UPDATE EMPLOYEES_TEMP
  SET FIRST_NAME = LPAD('1', 1000, '*'), LAST_NAME = LPAD('1', 1000, '*'), EMAIL = LPAD('1', 1000, '*'),
  PHONE_NUMBER = LPAD('1', 1000, '*');
COMMIT;
---行迁移优化前,先看看该语句逻辑读情况(执行计划及代价都一样,没必要展现了,就展现statistics即可)
SET AUTOTRACE traceonly statistics
set linesize 1000
select /*+index(EMPLOYEES_TEMP,idx_emp_id)*/ * from EMPLOYEES_TEMP  where employee_id>0;
/
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        219  consistent gets
          0  physical reads
          0  redo size
     437663  bytes sent via SQL*Net to client
        496  bytes received via SQL*Net from client
          9  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        107  rows processed
set autotrace off
----- 发现存在行迁移的方法
--首先建chaind_rows相关表,这是必需的步骤
@?/rdbms/admin/utlchain.sql
----以下命令针对EMPLOYEES_TEMP表和EMPLOYEES_TEMP_BK做分析,将产生行迁移的记录插入到chained_rows表中
analyze table EMPLOYEES_TEMP list chained rows into chained_rows;

注意:这里只能用analyze table,不能使用dbms_stats,具体请参见
http://czmmiao.iteye.com/blog/1483190
analyze table EMPLOYEES_TEMP compute statistics;
select count(*)  from chained_rows where table_name='EMPLOYEES_TEMP';
---以下方法可以去除行迁移
drop table EMPLOYEES_TEMP_TMP;
create table EMPLOYEES_TEMP_TMP as select * from EMPLOYEES_TEMP where rowid in (select head_rowid from chained_rows);
Delete from EMPLOYEES_TEMP where rowid in (select head_rowid from chained_rows);
Insert into EMPLOYEES_TEMP select * from EMPLOYEES_TEMP_TMP;
delete from chained_rows ;
commit;
analyze table EMPLOYEES_TEMP list chained rows into chained_rows;
select count(*)  from chained_rows where table_name='EMPLOYEES_TEMP';
--这时的取值一定为0,用这种方法做行迁移消除!
---行迁移优化后,先看看该语句逻辑读情况(执行计划及代价都一样,没必要展现了,就展现statistics即可)
SET AUTOTRACE traceonly statistics
set linesize 1000
select /*+index(EMPLOYEES_TEMP,idx_emp_id)*/ * from EMPLOYEES_TEMP  where employee_id>0;
/
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
       9221  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
行迁移消除后逻辑读明显减少。

行链接

当一个BLOCK不足以存放下一条记录的时候,就会发生行连接,这个时候oracle会把这条记录分成几个部分,分别存放在几个block中,然后把这几个block chain起来。行连接同样会影响性能,因为读一条记录至少会读两个BLOCK.

行链接实验
继续扩大字段
alter table EMPLOYEES modify FIRST_NAME VARCHAR2(2000);
alter table EMPLOYEES modify LAST_NAME  VARCHAR2(2000);
alter table EMPLOYEES modify EMAIL VARCHAR2(2000);
alter table EMPLOYEES modify PHONE_NUMBER  VARCHAR2(2000);
--- PCTFREE试验准备之更新表
UPDATE EMPLOYEES
  SET FIRST_NAME = LPAD('1', 2000, '*'), LAST_NAME = LPAD('1', 2000, '*'), EMAIL = LPAD('1', 2000, '*'),
  PHONE_NUMBER = LPAD('1', 2000, '*');
COMMIT;
---行链接移优化前,先看看该语句逻辑读情况
SET AUTOTRACE traceonly statistics
set linesize 1000
select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES  where employee_id>0
/

 

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        324  consistent gets
          0  physical reads
          0  redo size
     868528  bytes sent via SQL*Net to client
        496  bytes received via SQL*Net from client
          9  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        107  rows processed
set autotrace off
----以下命令针对EMPLOYEES表和EMPLOYEES_BK做分析,将产生行迁移的记录插入到chained_rows表中
analyze table EMPLOYEES list chained rows into chained_rows;
select count(*)  from chained_rows where table_name='EMPLOYEES';
---用消除行迁移的方法根本无法消除行链接!!!
drop table EMPLOYEES_TMP;
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;
--发现用消除行迁移的方法根本无法消除行链接!
analyze table EMPLOYEES list chained rows into chained_rows;
select count(*)  from chained_rows where table_name='EMPLOYEES';
COUNT(*)

---------------
321
---------------------------------------------------------------------------------
---启动大小为16K的块新建表空间(
--行链接只有通过加大BLOCK块的方式才可以避免,如下:
create tablespace dba_16k
blocksize 16K
datafile  '/home/oracle/dba_16k.DBF' size 100M 
autoextend on 
extent management local
segment space management auto;
alter table EMPLOYEES_TEMP move tablespace dba_16k;
alter index idx_emp_id rebuild ;
delete from chained_rows ;
commit;
analyze table EMPLOYEES_BK list chained rows into chained_rows;
select count(*)  from chained_rows where table_name='EMPLOYEES_TEMP';
COUNT(*)

---------------
0


SET AUTOTRACE traceonly statistics
set linesize 1000
select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES  where employee_id>0
/
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        116  consistent gets
          0  physical reads
          0  redo size
     866745  bytes sent via SQL*Net to client
        496  bytes received via SQL*Net from client
          9  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        107  rows processed

参考至:http://blog.csdn.net/robinson1988/article/details/4728717

              《基于案例学习sql优化》著梁剑斌

如有错误,欢迎指正

邮箱:czmcj@163.com

0
0
分享到:
评论

相关推荐

    Oracle 行迁移与行链接的实验详解

    当一条记录被更新的时候,数据库引擎首先会尝试在它保存的数据块中寻找足够的空闲空间,如果没有足够的空闲空间可用,这条记录将被...第二部分包含所有的具体数据,将保存到另外一个新的数据块中,这个就成了行迁移。

    2020_Oracle19c数据迁移图文详解.docx

    本文档用于手把手教0基础的小白通过使用oracle数据泵技术来实现数据迁移。该文档非常详细,如果看了文档你还不会,记得叫人打我,一定要叫人来打我。如果对你有作用,请记得点个关注,谢谢

    oracle迁移达梦常见问题汇总

    本文主要结合之前一次oracle迁移达梦的项目,将碰到的问题以及一系列踩过的坑列举出来供大家参考,数据库版本是达梦7。(本文中涉及到的部分对象名已用sch1,tab1等方式替换) 1、整体情况 迁移过程中失败任务数低于5%...

    Oracle跨平台迁移技术详解

    Oracle跨平台迁移技术详解,文档详细概述了oracle与oracle不同版本之间,oracle与不同异构数据库直接跨平台迁移技术详细解说,一书在手,数据库迁移不是问题!

    sqlserver和oracle数据迁移方案

    详解了sqlserver和oracle数据库之间的数据迁移

    Oracle10g数据泵操作步骤详解

    Oracle10g数据泵操作步骤详解 用数据泵导出可提高数据库导入导出性能

    oracle数据库导入到SQL server.docx

    利用 Microsoft SQL Server Migration Assistant for Oracle.exe(微软数据库迁移工具) ,将oracle数据库迁移数据到SQL server详解。

    oracle项目--DataBase Migration(数据库迁移)PPT

    自己做的oracle项目--DataBase Migration(数据库迁移),做了一个月的东西,里面包括四种方案,其中有SQLWAYS和POWERDESIGNER的详解

    Oracle数据库学习指南

    37. 如何在oracle7和oracle8之间exp-imp数据 38. 如何在Windows 2000下将Oracle完全卸载 39. 如何正确建立TYPE、partition(分区) 40. 如何正确利用Rownum来限制查询所返回的行数 41. 什么是ROWID,为什么需要...

    oracle exp imp详解

    导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理...

    oracle 数据泵详解

    oracle 10g 以后出现了数据泵,可以方便我们把低版本的数据库数据向高版本的数据库迁移

    LINUX下Oracle数据导入导出的方法详解

    本文讲述了LINUX下Oracle数据导入导出的方法。分享给大家供大家参考,具体如下: 一. 导出工具 exp 1. 它是操作系统下一个可执行的文件 存放目录/ORACLE_HOME/bin exp导出工具将数据库中数据备份压缩成一个二进制...

    oracle详解

    导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理...

    Oracle DBA调优技术学习笔记

    Oracle 12c-优化 Hint详解.pdf Oracle 12c-优化 Oracle 索引技术.pdf Oracle 12c 执行计划.pdf Oracle 12c锁.pdf Oracle 12c查询优化器.pdf Oracle 12c 使用绑定变量 VS 不使用绑定变量.pdf Oracle 12c 自动工作负载...

    oracle_exp_imp详解

    导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理...

    Oracl技术资料(EBook)

    电子版的Oracl技术资料 1. 《Oracle8 优化技术》摘录 (第一章 安装) 2. 《Oracle8 优化技术》摘录 (第二章 内存-CPU) 3. 《Oracle8 优化技术》摘录 (第三章 输入-...46.Oracle 数据库向 MS SQL Server 7.0 的迁移

    2021 云和恩墨大讲堂PPT汇总(50份).zip

    经典知识库:Oracle数据库索引分裂详解 经典知识库:PostgreSQL中的锁 经典知识库:SQL条件等价改写秘笈 如何实现海量数据迁移及落地实践 如何通过APEX 实现标准化运维 如何通过APEX实现标准化运维sql 深入解析:...

    EXP IMP详解

    导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理...

    Oracle统计信息的导出导入测试示例详解

    比如在数据库迁移前后,希望统计信息保持不变;又比如想对统计信息重新进行收集,但是担心重新收集的结果反而引发性能问题,想先保存当前的统计信息,这样即使重新收集后效果不好还可以导入之前的统计信息。 Oracle...

    oracle学习经典教程

    1.2 索引详解..................28 1.2.1 索引介绍.........28 1.2.1.1 索引的创建语法......28 1.2.1.2 索引特点..................28 1.2.1.3 索引不足..................29 1.2.1.4 应该建索引列...

Global site tag (gtag.js) - Google Analytics