行迁移和行链接
时间:2021-09-08
本文章向大家介绍行迁移和行链接,主要包括行迁移和行链接使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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;
原文地址:https://www.cnblogs.com/hanglinux/p/15244093.html
- 谈谈个人网站的建立(七)—— 那些建站必备的插件
- 【美团技术团队博客】Linux资源管理之cgroups简介
- 谈谈个人网站的建立(六)—— 数据库同步
- Javascript解析机制 执行机制
- Tomcat9源码——编译环境搭建
- 谈谈个人网站的建立(五)—— 小集群的部署
- 跟Google学写代码--Chromium/base--cpu源码学习及应用
- Spring项目路径
- 跟Google学写代码--Chromium/base--stl_util源码学习及应用
- libphonenumber--windows上编译libphonenumber.lib以及使用(C++、VS2015)
- querySelector与querySelectorAll
- 【技术博客】Spark性能优化指南——基础篇
- 移动端兼容系列 HTML与CSS兼容
- 保存到配置文件
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法