`

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 行迁移与行链接的实验详解

    ### Oracle 行迁移与行链接的实验详解 #### 一、引言 在Oracle数据库管理过程中,行迁移(row migration)与行链接(row chaining)是两种常见的现象,它们通常发生在记录过大或更新操作导致记录扩展超出单个数据块所能...

    oracle_行链接和行迁移

    ### Oracle行链接和行迁移详解 #### 一、概述 Oracle数据库中,行链接和行迁移是两种可能影响数据库性能的现象。了解这两种现象的发生原因及其处理方法对于优化Oracle数据库至关重要。 #### 二、Oracle块 Oracle...

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

    ### Oracle 19c 数据迁移图文详解 #### 知识点概述 本文旨在详细介绍如何使用Oracle数据泵技术完成从Oracle 11g到Oracle 19c的数据迁移工作。数据迁移是一个复杂的过程,尤其是在源数据库与目标数据库存在字符集...

    oracle数据库迁移实例01

    综上所述,在Windows环境下实现Oracle数据库迁移,尤其是当db_name和instance_name不同时,需要仔细规划每一步操作,并充分考虑各种配置差异带来的影响。通过以上步骤,可以有效确保迁移的成功率和数据的完整性。

    oracle迁移达梦常见问题汇总

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

    oracle rac数据迁移

    ### Oracle RAC 数据迁移知识点详解 #### 一、Oracle RAC 数据迁移背景及意义 在企业信息化建设过程中,Oracle RAC (Real Application Clusters) 作为高性能、高可用性的数据库解决方案,被广泛应用在各种关键业务...

    oracle数据库迁移步骤

    ### Oracle数据库迁移步骤详解 #### 一、Oracle数据库迁移概述 在进行Oracle数据库迁移时,尤其是在从旧版本向新版本迁移的过程中,确保数据的一致性和完整性至关重要。Oracle提供了多种工具和技术来实现这一点,...

    Oracle单机通过rman迁移到RAC集群.docx

    为了提高系统的可用性、可扩展性和性能,通常需要将原有的单机Oracle数据库迁移到RAC(Real Application Clusters)集群上。这种迁移方式不仅可以提升系统的稳定性和可靠性,还能更好地支持高并发的应用场景。 ####...

    Oracle跨平台迁移技术详解

    ### Oracle跨平台迁移技术详解 #### 一、概述 随着企业业务的发展和技术更新换代,数据库的跨平台迁移成为了一项常见的任务。特别是在Oracle数据库领域,由于其广泛的使用范围和强大的功能,使得Oracle数据库的...

    oracle数据迁移

    ### Oracle 数据迁移详解 在企业级应用环境中,Oracle 数据库作为主流的关系型数据库管理系统之一,在数据迁移场景下具有广泛的应用需求。本文将基于提供的“Oracle 数据迁移”文档内容,深入探讨 Oracle 数据迁移...

    mydql--oracle项目迁移简说

    《Oracle项目迁移至MySQL——mydql工具详解》 在IT行业中,数据库迁移是一项常见的任务,尤其是在企业系统升级、架构调整或数据迁移服务时。本文将深入探讨如何使用mydql工具将Oracle数据库项目平滑地迁移到MySQL,...

    SQLSERVER到ORACLE的数据库迁移

    ### SQL Server到Oracle数据库迁移详解 #### 一、引言 随着企业的发展和技术的更新换代,企业常常需要对原有的数据库系统进行迁移或升级。本文将详细介绍如何使用Java语言实现从SQL Server到Oracle数据库的数据...

    Mysql迁移Oracle方案

    ### MySQL 迁移至 Oracle 方案详解 #### 一、环境准备 在进行MySQL到Oracle的数据迁移之前,首先需要做好一系列的准备工作。 ##### 1.1 导入机 - **安装Oracle 11g数据库**:确保安装过程中正确配置数据库的各项...

    数据库迁移oracle到DM.docx

    - 这一步需要明确迁移的具体类型,本例中为“Oracle迁移到DM7”。 4. **输入Oracle数据库信息**: - 配置源Oracle数据库的信息,包括数据库地址、端口号、用户名、密码等必要参数,并点击“下一步”。 5. **输入...

    xx生产系统oracle数据库迁移.docx

    Oracle 数据库迁移是指将 Oracle 数据库从一台服务器迁移到另一台服务器上,这个过程需要对数据库进行备份、传输和恢复。以下是 Oracle 数据库迁移的知识点: 一、操作目的 * 利用 NFS 和 RMAN 的 copy 命令,将 ...

    oracle数据库数据文件迁移的方法1

    ### Oracle数据库数据文件迁移的方法详解 #### 背景与目的 在Oracle数据库管理中,随着业务的增长,可能会遇到磁盘空间不足的情况。此时,为了确保业务连续性和数据安全性,通常需要将某些数据文件迁移到其他存储...

    oracle执行计划详解

    Oracle 执行计划详解是数据库管理系统中一个非常重要的概念。本文将详细介绍 Oracle 执行计划的相关概念、访问数据的存取方法、表之间的连接等内容,并对总结和概述,以便于理解和记忆。 一、相关的概念 1. Rowid ...

Global site tag (gtag.js) - Google Analytics