Oracle 行迁移和行链接
一、行迁移
1.1、行迁移概念
当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移。一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址。因此整行数据都被移动,原始的数据块上仅仅保留的是指向新块的一个地址信息。
成因:当行被update时,如果update更新的行大于数据块的pctfree值,就需要申请第2个块,从而形成迁移。
后果:导致应用需要访问更多的数据块,性能下降。
预防:1.将数据块的pctfree调大;
2.针对表空间扩大数据块的大小。
检查:analyze table 表名 validate structure cascade into chained_rows;
2.1、实例:
实验说明:
(以EMPLOYEES表为例,如果涉及到该表有主键,并且有别的表的外键REFERENCE关联到本表,必须要执行步骤2和步骤7,否则不必执行);
1. 执行$ORACLE_HOME/rdbms/admin目录下的utlchain.sql脚本创建chained_rows表。
2. 禁用所有其它表上关联到此表上的所有限制(假想EMPLOYEES表有主键PK_EMPLOYEES_ID,假想test表有外键f_employees_id关联reference到employees表)。
select index_name,index_type,table_name from user_indexes where table_name='EMPLOYEES';
select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME from USER_CONSTRAINTS where R_CONSTRAINT_NAME='PK_EMPLOYEES_ID';
alter table test disable constraint f_employees_id;
3. 将存在有行迁移的表(用table_name代替)中的产生行迁移的行的rowid放入到chained_rows表中。
4. 将表中的行迁移的row id放入临时表中保存。
5. 删除原来表中存在的行迁移的记录行。
6. 从临时表中取出并重新插入那些被删除了的数据到原来的表中,并删除临时表。
7. 启用所有其它表上关联到此表上的所有限制。
alter table test enable constraint f_employees_id;
此外还可以采用move和exp/imp的方式(特别注意move会导致索引失效,需要重建索引)。
- ----创建实验表----
- SQL> DROP TABLE EMPLOYEES PURGE;
- DROP TABLE EMPLOYEES PURGE
- *
- 第 1 行出现错误:
- ORA-00942: 表或视图不存在
- SQL> CREATE TABLE EMPLOYEES AS SELECT * FROM HR.EMPLOYEES ;
- 表已创建。
- SQL> desc EMPLOYEES;
- 名称 是否为空? 类型
- ----------------------------------------- -------- ----------------------------
- EMPLOYEE_ID NUMBER(6)
- FIRST_NAME VARCHAR2(20)
- LAST_NAME NOT NULL VARCHAR2(25)
- EMAIL NOT NULL VARCHAR2(25)
- PHONE_NUMBER VARCHAR2(20)
- HIRE_DATE NOT NULL DATE
- JOB_ID NOT NULL VARCHAR2(10)
- SALARY NUMBER(8,2)
- COMMISSION_PCT NUMBER(2,2)
- MANAGER_ID NUMBER(6)
- DEPARTMENT_ID NUMBER(4)
- SQL> create index idx_emp_id on employees(employee_id);
- 索引已创建。
- ---扩大字段----
- SQL> alter table EMPLOYEES modify FIRST_NAME VARCHAR2(1000);
- 表已更改。
- SQL> alter table EMPLOYEES modify LAST_NAME VARCHAR2(1000);
- 表已更改。
- SQL> alter table EMPLOYEES modify EMAIL VARCHAR2(1000);
- 表已更改。
- SQL> alter table EMPLOYEES modify PHONE_NUMBER VARCHAR2(1000);
- 表已更改。
- SQL> desc employees;
- 名称 是否为空? 类型
- ----------------------------------------- -------- ----------------------------
- EMPLOYEE_ID NUMBER(6)
- FIRST_NAME VARCHAR2(1000)
- LAST_NAME NOT NULL VARCHAR2(1000)
- EMAIL NOT NULL VARCHAR2(1000)
- PHONE_NUMBER VARCHAR2(1000)
- HIRE_DATE NOT NULL DATE
- JOB_ID NOT NULL VARCHAR2(10)
- SALARY NUMBER(8,2)
- COMMISSION_PCT NUMBER(2,2)
- MANAGER_ID NUMBER(6)
- DEPARTMENT_ID NUMBER(4)
- ----更新表----
- SQL> UPDATE EMPLOYEES
- 2 SET FIRST_NAME = LPAD('', 1000, '*'), LAST_NAME = LPAD('', 1000, '*'), EMAIL = LPAD('', 1000, '*'),
- 3 PHONE_NUMBER = LPAD('', 1000, '*');
- 已更新107行。
- SQL> commit;
- 提交完成。
- ----行迁移优化前,先看看该语句逻辑读情况(执行计划及代价都一样,没必要展现了,就展现statistics即可)----
- SQL> set autotrace traceonly stat
- SQL> set linesize 1000
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 已选择107行。
- 统计信息
- ----------------------------------------------------------
- 152 recursive calls
- 0 db block gets
- 310 consistent gets
- 0 physical reads
- 0 redo size
- 437664 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 已选择107行。
- 统计信息
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 219 consistent gets
- 0 physical reads
- 0 redo size
- 437664 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
- SQL> set autotrace off
- ----- 发现存在行迁移的方法
- --首先建chaind_rows相关表,这是必需的步骤
- SQL> drop table chained_rows purge;
- drop table chained_rows purge
- *
- 第 1 行出现错误:
- ORA-00942: 表或视图不存在
- SQL> @?/rdbms/admin/utlchain.sql
- 表已创建。
- ----以下命令针对EMPLOYEES表和EMPLOYEES_BK做分析,将产生行迁移的记录插入到chained_rows表中
- SQL> analyze table EMPLOYEES list chained rows into chained_rows;
- 表已分析。
- SQL> select count(*) from chained_rows where table_name='EMPLOYEES';
- COUNT(*)
- ----------
- 105
- ---以下方法可以去除行迁移
- SQL> drop table EMPLOYEES_TMP;
- drop table EMPLOYEES_TMP
- *
- 第 1 行出现错误:
- ORA-00942: 表或视图不存在
- SQL> create table EMPLOYEES_TMP as select * from EMPLOYEES where rowid in (select head_rowid from chained_rows);
- 表已创建。
- SQL> Delete from EMPLOYEES where rowid in (select head_rowid from chained_rows);
- 已删除105行。
- SQL> Insert into EMPLOYEES select * from EMPLOYEES_TMP;
- 已创建105行。
- SQL> delete from chained_rows ;
- 已删除105行。
- SQL> commit;
- 提交完成。
- SQL> analyze table EMPLOYEES list chained rows into chained_rows;
- 表已分析。
- SQL> select count(*) from chained_rows where table_name='EMPLOYEES';
- COUNT(*)
- ----------
- 0
- --这时的取值一定为0,用这种方法做行迁移消除,肯定是没问题的!
- ---行迁移优化后,先看看该语句逻辑读情况(执行计划及代价都一样,没必要展现了,就展现statistics即可)
- SET AUTOTRACE traceonly statistics
- SQL> set linesize 1000
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 已选择107行。
- 统计信息
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 116 consistent gets
- 0 physical reads
- 0 redo size
- 437034 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
二、行链接
2.1、行链接概念
当一行数据太大而不能在一个单数据块容纳时,行链接由此产生。举例来说,当你使用了4kb的Oracle数据块大小,而你需要插入一行数据是8k,Oracle则需要使用3个数据块分成片来存储。因此,引起行链接的情形通常是,表上行记录的大小超出了数据库Oracle块的大小。
产生原因:当一行数据大于一个数据块,ORACLE会同时分配两个数据块,并在第一个块上登记第二个块的地址,从而形成行链接。
预防方法:针对表空间扩大数据块大小。
检查:analyze table 表名 validate structure cascade into chained_rows;
- ----建表----
- SQL> DROP TABLE EMPLOYEES PURGE;
- 表已删除。
- SQL> CREATE TABLE EMPLOYEES AS SELECT * FROM HR.EMPLOYEES ;
- 表已创建。
- SQL> set linesize 80;
- SQL> desc EMPLOYEES;
- 名称 是否为空? 类型
- ----------------------------------------- -------- ----------------------------
- EMPLOYEE_ID NUMBER(6)
- FIRST_NAME VARCHAR2(20)
- LAST_NAME NOT NULL VARCHAR2(25)
- EMAIL NOT NULL VARCHAR2(25)
- PHONE_NUMBER VARCHAR2(20)
- HIRE_DATE NOT NULL DATE
- JOB_ID NOT NULL VARCHAR2(10)
- SALARY NUMBER(8,2)
- COMMISSION_PCT NUMBER(2,2)
- MANAGER_ID NUMBER(6)
- DEPARTMENT_ID NUMBER(4)
- SQL> create index idx_emp_id on employees(employee_id);
- 索引已创建。
- ----扩大字段----
- SQL> alter table EMPLOYEES modify FIRST_NAME VARCHAR2(2000);
- 表已更改。
- SQL> alter table EMPLOYEES modify LAST_NAME VARCHAR2(2000);
- 表已更改。
- SQL> alter table EMPLOYEES modify EMAIL VARCHAR2(2000);
- 表已更改。
- SQL> alter table EMPLOYEES modify PHONE_NUMBER VARCHAR2(2000);
- 表已更改。
- ----更新表----
- UPDATE EMPLOYEES
- SET FIRST_NAME = LPAD('', 2000, '*'), LAST_NAME = LPAD('', 2000, '*'), EMAIL = LPAD('', 2000, '*'),
- PHONE_NUMBER = LPAD('', 2000, '*');
- COMMIT;
- 已更新107行。
- SQL>
- 提交完成。
- -----行链接移优化前,先看看该语句逻辑读情况
- SET AUTOTRACE traceonly
- SQL> set linesize 1000
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 统计信息
- ----------------------------------------------------------
- 153 recursive calls
- 1 db block gets
- 415 consistent gets
- 0 physical reads
- 176 redo size
- 868529 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 已选择107行。
- 统计信息
- ----------------------------------------------------------
- 7 recursive calls
- 0 db block gets
- 397 consistent gets
- 0 physical reads
- 0 redo size
- 868529 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
- SQL> set autotrace off
- --------- 发现存在行链接的方法
- --首先建chaind_rows相关表,这是必需的步骤
- SQL> drop table chained_rows purge;
- 表已删除。
- SQL> @?/rdbms/admin/utlchain.sql
- 表已创建。
- ----以下命令针对EMPLOYEES表和EMPLOYEES_BK做分析,将产生行迁移的记录插入到chained_rows表中
- SQL> analyze table EMPLOYEES list chained rows into chained_rows;
- 表已分析。
- SQL> select count(*) from chained_rows where table_name='EMPLOYEES';
- COUNT(*)
- ----------
- 107
- ---用消除行迁移的方法根本无法消除行链接!!!
- SQL> drop table EMPLOYEES_TMP;
- 表已删除。
- SQL> create table EMPLOYEES_TMP as select * from EMPLOYEES where rowid in (select head_rowid from chained_rows);
- 表已创建。
- SQL> Delete from EMPLOYEES where rowid in (select head_rowid from chained_rows);
- 已删除107行。
- SQL> Insert into EMPLOYEES select * from EMPLOYEES_TMP;
- 已创建107行。
- SQL> delete from chained_rows ;
- 已删除107行。
- SQL> commit;
- 提交完成。
- --发现用消除行迁移的方法根本无法消除行链接!
- SQL> analyze table EMPLOYEES list chained rows into chained_rows;
- 表已分析。
- SQL> select count(*) from chained_rows where table_name='EMPLOYEES';
- COUNT(*)
- ----------
- 107
- SQL> SET AUTOTRACE traceonly stat
- SQL> select /*+index(EMPLOYEES,idx_emp_id)*/ * from EMPLOYEES where employee_id>0;
- 已选择107行。
- 统计信息
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 223 consistent gets
- 0 physical reads
- 0 redo size
- 867923 bytes sent via SQL*Net to client
- 492 bytes received via SQL*Net from client
- 9 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 107 rows processed
- ---启动大小为32K的块新建表空间(WINDOWS下只能使用2K,4K,8K和16K)
- --行链接只有通过加大BLOCK块的方式才可以避免,如下:
- create tablespace TBS_JACK_16k
- blocksize 16k
- datafile '/u01/app/oracle/oradata/orcl/TBS_JACK_32K_01.dbf' size 100m
- autoextend on
- extent management local
- 6 segment space management auto;
- create tablespace TBS_JACK_16k
- *
- 第 1 行出现错误:
- ORA-29339: 表空间块大小 16384 与配置的块大小不匹配
- ------------------ORA-29339报错解决办法!
- ----解决问题后再次创建表空间----
- SQL> /
- 表空间已创建。
- SQL> DROP TABLE EMPLOYEES_BK PURGE;
- DROP TABLE EMPLOYEES_BK PURGE
- *
- 第 1 行出现错误:
- ORA-00942: 表或视图不存在
- SQL> CREATE TABLE EMPLOYEES_BK TABLESPACE TBS_JACK_16K AS SELECT * FROM EMPLOYEES;
- 表已创建。
- SQL> delete from chained_rows ;
- 已删除107行。
- SQL> analyze table EMPLOYEES_BK list chained rows into chained_rows;
- 表已分析。
- SQL> select count(*) from chained_rows where table_name='EMPLOYEES_BK';
- COUNT(*)
- ----------
- 0
Oracle 行迁移和行链接的更多相关文章
- 模拟Oracle行迁移和行链接
行链接消除方法创建大的block块------------------ 参考tom kyte的例子----------------------------------------------创建4k ...
- oracle 11g sql优化之行迁移处理(加大BLOCK块)
行链接 产生原因:当一行数据大于一个数据块,ORACLE会同时分配两个数据块,并在第一个块上登记第二个块的地址,从而形成行链接. 预防方法:针对表空间扩大数据块大小.检查:analyze table ...
- [20180327]行迁移与ITL浪费.txt
[20180327]行迁移与ITL浪费.txt --//生产系统遇到的一个问题,增加一个字段到表结构,修改数据字典,导致出现行迁移,而更加严重的是没有修改pctfree值,--//以后的业务操作,依旧 ...
- 【oracle11g,17】存储结构: 段的类型,数据块(行连接、行迁移,块头),段的管理方式,高水位线
一.段的类型: 1.什么是段:段是存储单元. 1.段的类型有: 表 分区表 簇表 索引 索引组织表(IOT表) 分区索引 暂时段 undo段 lob段(blob ,clob) 内嵌表(record类型 ...
- oracle 分组取第一行数据 ,查询sql语句
oracle 分组取第一行数据 SELECT * FROM ( SELECT ROW_NUMBER() OVER(PARTITION BY x ORDER BY y DESC) rn, t.* FR ...
- Oracle JDK迁移指南
Oracle JDK迁移指南 https://docs.oracle.com/en/java/javase/11/migrate/index.html#JSMIG-GUID-C25E2B1D-6C24 ...
- Oracle 数据库迁移到MySQL (kettle,navicate,sql developer等工具
Oracle 数据库迁移到MySQL (kettle,navicate,sql developer等工具 1 kettle --第一次使用kettle玩迁移,有什么不足之处和建议,请大家指正和建议. ...
- Oracle 服务器迁移的一些经验
前言 通过此文章来分享一下 Oracle 服务器迁移过程中的一些经验,希望对大家有些许帮助. 本文旨在帮助更多的同学,会提及一些基本命令或技巧,但不赘述,后续有机会再进一步分享各个细节. 背景 之前因 ...
- jquery Datatables 行数据删除、行上升、行下降功能演示
Datatables 是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 官方网站:http://www.datatables.net Datatables ...
随机推荐
- Redis一些基本的操作
代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...
- 教你安装CentOS 6.5如何选择安装包
近来发现越来越多的运维小伙伴们都有最小化安装CentOS 6.5系统的洁癖,因此,找老男孩来咨询,这个“洁癖”好习惯啊,必须支持,,因此发布本文和大家分享下. (1)系统安装类型选择及自定义额外包组 ...
- hadoop map reduce 实例wordcount的使用
hadoop jar hadoop-mapreduce-examples-2.7.3.jar wordcount /wordcount.txt /wc/output3
- 如何调试DLL组件
因为DLL组件不像EXE是程序的入口,所以DLL需要其他进程的调用才能调试. 1.首先在DLL项目中你想调试的位置打好断点. 2.如果已经有一个进程,比如foo.exe已经启动,那么就用:调试> ...
- category分类
/* 使用继承关系来扩充一个类,有一个弊病,高耦合性 category(分类,类别) 能够帮我们扩充一个类的功能 */ - (void)superJump { // [self eat]; [s ...
- JAVA NIO系列(三) Buffer 解读
缓冲区分类 NIO中的buffer用于和通道交互,数据是从通道读入缓冲区,从缓冲区中写入通道的.Buffer就像一个数组,可以保存多个类型相同的数据.每种基本数据类型都有对应的Buffer类: 缓冲区 ...
- PostgreSQL Replication之第十一章 使用Skytools(5)
11.5 关于walmgr 的介绍 walmgr 是一个简化基于文件事务日志传输的工具.早在过去的一些日子里(在9.0版本之前),使用walmgr来简化基本备份是很常见的.随着流复制的引入,情况有了一 ...
- java-语法
JAVA语法 1.标识符 1.定义:对各种变量.方法.类等进行命名的字符序列 2.规则:他的组成由字母.数字.$,数字不能出现在开始,不能和关键字重复,区分大小写 2.数据类型 1.分类 1基本数据类 ...
- codevs 1204 寻找子串位置
http://codevs.cn/problem/1204/ 1204 寻找子串位置 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题解 查看运行结果 ...
- 数据库SQL CRUD
1.删除表 drop table +表名 2.修改表 alter table+表名+ add(添加)+列名+ int(类型) alter table+表名+ drop(删除)+column(列) ...