关于Oracle数据库中行迁移/行链接的问题(一)
在实际的工作中我们经常会碰到一些Oracle数据库性能较低的问题,当然,引起Oracle数据库性能较低的原因是多方面的,我们能够通过一些正确的设计和诊断来尽量的避免一些Oracle数据库性能不好,Row Migration (行迁移) & Row Chaining (行链接)就是其中我们可以尽量避免的引起Oracle数据库性能低下的潜在问题。通过合理的诊断行迁移/行链接,我们可以较大幅度上提高Oracle数据库的性能。
那究竟什么是行迁移/行链接呢,先让我们从Oracle的block开始谈起。
操作系统的最小读写操作单元是操作系统的block,所以当创建一个Oracle数据库的时候我们应该讲数据库的block size设置成为操作系统的block size的整数倍,Oracle block是Oracle数据库中读写操作的最小单元,Oracle9i之前的Oracle数据库版本中Oracle block一旦在创建数据库的时候被设定后就没法再更改。为了在创建数据库之前确定一个合理的Oracle block的大小,我们需要考虑一些因素,例如数据库本身的大小以及并发事务的数量等。使用一个合适的Oracle block大小对于数据库的调优是非常重要的。Oracle block的结构如下图所示:
图一:Oracle Block结构图
由上图我们可以看出,一个Oracle block由三个部分组成,分别是数据块头、自由空间、实际数据三部份组成。
数据块头:主要包含有数据块地址的一些基本信息和段的类型,以及表和包含有数据的实际行的地址。
自由空间:是指可以为以后的更新和插入操作分配的空间,大小由PCTFREE和PCTUSED两个参数影响。
实际数据:是指在行内存储的实际数据。
当创建或者更改任何表和索引的时候,Oracle在空间控制方面使用两个存储参数:
PCTFREE:为将来更新已经存在的数据预留空间的百分比。
PCTUSED:用于为插入一新行数据的最小空间的百分比。这个值决定了块的可用状态。可用的块时可以执行插入的块,不可用状态的块只能执行删除和修改,可用状态的块被放在freelist中。
当表中一行的数据不能在一个数据block中放入的时候,这个时候就会发生两种情况,一种是行链接,另外一种就是行迁移了。
行链接产生在第一次插入数据的时候如果一个block不能存放一行记录的情况下。这种情况下,Oracle将使用链接一个或者多个在这个段中保留的block存储这一行记录,行链接比较容易发生在比较大的行上,例如行上有LONG、LONG RAW、LOB等数据类型的字段,这种时候行链接是不可避免的会产生的。
当一行记录初始插入的时候事可以存储在一个block中的,由于更新操作导致行长增加了,而block的自由空间已经完全满了,这个时候就产生了行迁移。在这种情况下,Oracle将会迁移整行数据到一个新的block中(假设一个block中可以存储下整行数据),Oracle会保留被迁移行的原始指针指向新的存放行数据的block,这就意味着被迁移行的ROW ID是不会改变的。
当发生了行迁移或者行链接,对这行数据操作的性能就会降低,因为Oracle必须要扫描更多的block来获得这行的信息。
下面举例来具体说明行迁移/行链接的产生过程。
先创建一个pctfree为20和pctused为50的测试表:
create table test(
col1 char(20),
col2 number)
storage (
pctfree 20
pctused 50);
当插入一条记录的时候,Oracle会在free list中先去寻找一个自由的块,并且将数据插入到这个自由块中。而在free list中存在的自由的块是由pctfree值决定的。初始的空块都是在free list中的,直到块中的自由空间达到pctfree的值,此块就会从free list中移走,而当此块中的使用空间低于pctused的时候,此块又被重新放到free list中。
Oracle使用free list机制可以大大的提高性能,对于每次的插入操作,Oracle只需要查找free list就可以了,而不是去查找所有的block来寻找自由空间。
假设第一次插入数据使用的一个空的block,如下图所示:
图二:Oracle空的block结构图
假设插入第一条记录的时候占用一个block的10%的空间(除去block头占去的大小),剩余的自由空间90%大于pctfree20%,因此这个block还将继续为下次的插入操作提供空间。
再连续插入七条记录,使block的剩余自由空间剩下20%,此时,这个block将要从free list中移走,如果再插入记录,Oracle将再free list中寻找下一个空余的block去存放后来插入的数据。
图四:插入80%后的Oracle block结构图
此时如果去更新第一条插入的记录,使其行长增加15%,Oracle将会使用这个block中剩余的20%的自由空间来存放此行数据,如果再更新第二条记录,同样的使其行长增加15%,而此block中只剩下5%的自由空间,不够存放更新的第二条记录,于是Oracle会在free list中寻找一个有自由空间(10%+15%)的block来存放这行记录的block去存储,在原来的block中保存了指向新的block的指针,原来这行记录的ROW ID保持不变,这个时候就产生了行迁移。
而当我们插入一条新纪录的时候,如果一个blcok不足以存放下这条记录,Oracle就会寻找一定数量的block一起来容纳这条新的记录,这个时候就产生了行链接,行链接主要产生在LOB、CLOB、BLOB和大的VA行链接HAR2数据类型上。
具体我们通过下面的一个试验来查看行链接和行迁移是如何产生并在数据文件中体现出来的。
先查看ALLAN这个表空间的数据文件号,为了便于测试,我只建立了一个数据文件。
SQL> select file_id from dba_data_files where tablespace_name='ALLAN';
FILE_ID
----------
23
创建一个测试表test:
SQL> create table test ( x int primary key, a char(2000), b char(2000), c char(2000), d char(2000), e char(2000) ) tablespace allan;
Table created.
因为我的数据库的db_block_size是8K,所以我创建的表有五个字段,每个占2000个字节,这样一行记录大约10K,就能超过一个block的大小了。
然后插入一行记录,只有一个字段的:
SQL> insert into test(x) values (1);
1 row created.
SQL> commit;
Commit complete.
查找这行记录所在的block,并dump出来:
SQL> select dbms_rowid.rowid_block_number(rowid) from test;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
34
SQL> alter system dump datafile 23 block 34;
System altered.
在udump目录下查看trace文件的内容如下:
Start dump data blocks tsn: 34 file#: 23 minblk 34 maxblk 34
buffer tsn: 34 rdba: 0x05c00022 (23/34)
scn: 0x0000.013943f3 seq: 0x01 flg: 0x02 tail: 0x43f30601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x05c00022
Object id on Block? Y
seg/obj: 0x3ccd csc: 0x00.13943ef itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000a.02e.00000ad7 0x00800036.03de.18 --U- 1 fsc 0x0000.013943f3
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
data_block_dump,data header at 0xadb505c
===============
tsiz: 0x1fa0
hsiz: 0x14
pbl: 0x0adb505c
bdba: 0x05c00022
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f9a
avsp=0x1f83
tosp=0x1f83
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f9a
block_row_dump:
tab 0, row 0, @0x1f9a
tl: 6 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 2] c1 02
end_of_block_dump
End dump data blocks tsn: 34 file#: 23 minblk 34 maxblk 34
对其中的一些信息做一些解释:
Fb:H是指行记录的头,L是指行记录的最后一列,F是指行记录的第一列。
Cc:列的数量
Nrid:对于行链接或者行迁移来说的下一个row id的值
由上面的dump信息我们可以看出来当前表test是没有行链接或者行迁移的。
然后更新test表,并重新dump出来:
SQL> update test set a='test',b='test',c='test',d='test',e='test' where x=1;
1 row updated.
SQL> commit;
Commit complete.
此时应该有行迁移/行链接产生了。
SQL> alter system dump datafile 23 block 34;
System altered.
在udump目录下查看trace文件的内容如下:
Start dump data blocks tsn: 34 file#: 23 minblk 34 maxblk 34
buffer tsn: 34 rdba: 0x05c00022 (23/34)
scn: 0x0000.0139442b seq: 0x01 flg: 0x02 tail: 0x442b0601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x05c00022
Object id on Block? Y
seg/obj: 0x3ccd csc: 0x00.1394429 itc: 2 flg: - typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000a.02e.00000ad7 0x00800036.03de.18 C--- 0 scn 0x0000.013943f3
0x02 0x0004.002.00000ae0 0x0080003b.0441.11 --U- 1 fsc 0x0000.0139442b
data_block_dump,data header at 0xadb505c
===============
tsiz: 0x1fa0
hsiz: 0x14
pbl: 0x0adb505c
bdba: 0x05c00022
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x178a
avsp=0x177c
tosp=0x177c
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x178a
block_row_dump:
tab 0, row 0, @0x178a
tl: 2064 fb: --H-F--N lb: 0x2 cc: 3
nrid: 0x05c00023.0
col 0: [ 2] c1 02
col 1: [2000]
74 65 73 74 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
............
col 2: [48]
74 65 73 74 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
end_of_block_dump
End dump data blocks tsn: 34 file#: 23 minblk 34 maxblk 34
我们不难看出,nrid出现了值,指向了下一个row id,证明刚刚的update操作使这行记录产生了行链接或者行迁移了。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html
转载于:https://blog.51cto.com/19880614/1198895
关于Oracle数据库中行迁移/行链接的问题(一)相关推荐
- Oracle数据库:约束行限制where语句,判断条件,比较条件,字符串日期格式,in,like,escape,null语句
Oracle数据库:约束行限制where语句,判断条件,比较条件,字符串日期格式,in,like,escape,null语句 2022找工作是学历.能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很 ...
- Oracle数据库之多行函数
oracle安装参照: Oracle数据库之安装教程 Oracle数据库总结: Oracle数据库之基本查询 Oracle数据库之单行函数 Oracle数据库之多行函数 Oracle数据库之多表查询 ...
- mysql连接oracle数据库服务器_Oracle 远程链接oracle数据库服务器的配置
远程链接oracle数据库服务器的配置 by:授客 QQ:1033553122 原理: 一.Oracle客户端与服务器端的通讯机制 1.OracleNet协议 如下图所示,Oracle通过Oracle ...
- 大容量Oracle数据库跨平台迁移案例(杭州电信3.5T帐务系统 IBM-HP)
客户背景 杭州电信是中国电信旗下的重要分公司之一.杭州电信的前身是创建于1883年的津沪电报总局杭州电报分局.解放后,随着我国邮电事业的变迁,杭州电信不断发展壮大.在2000年7月, 浙江省电信有限公 ...
- Oracle数据库备份迁移
前言 服务器要从A区迁到B区,下面记录了我迁移数据库的过程. 建议做任何事之前先规划好达到目的的步骤和所需进行的操作,并把流程拉起来,到时候按操作步骤一步步来,方便之余,更便于问题的排查(如果出了问题 ...
- oracle数据库数据迁移三部曲(一)oracle 11g的安装
本人在这学期跟随老师开发一个JavaEE的教师智能系统,遇到了一个问题,学校提供的数据库文件时oracle的dmp文件,而现在使用时mysql和sqlserver数据库,所以需要把oracle的dmp ...
- oracle锁表语句执行提示无法终止当前对话_显示Oracle数据库表或行上持有锁的所有会话...
Report Content Issue: * Copyright Infringment Spam Invalid Contents Broken Links Your Name: * Your E ...
- oracle 数据库数据迁移解决方案
大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移,接下来把心得与大家分享一下 去年年底做了不少系统的数据迁移,大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移, ...
- oracle数据库connectionstring,C#如何链接本地Oracle数据库 ConnectionString BadImageError报错...
如果你已经创建好了用户名密码.并且已经有了一个可以调用的table,直接跳到第3部分 1. 创建数据库用户名密码 Create the user create user TENANT01 identi ...
最新文章
- mysql+在服务中无法启动_MySQL服务初始化后无法启动
- [SDUT](3329)顺序表应用5:有序顺序表归并 ---有序表归并(线性表)
- Mysql 查看、创建、更改 数据库和表
- Spring Boot 开发web 项目
- 2021上饶市高考中考成绩查询,2021年上饶中考成绩公布查询时间 上饶中考成绩查询方式入口...
- js call,apply,bind三个方法的区别
- [代码阅读] ECS toString实现方法
- 电脑能玩和平精英吗_电脑玩和平精英灵敏度这样设置更流畅,还能匹配手机
- python的zipfile压缩文件夹_python zipfile压缩使用说明
- 龙芯录取通知书引争议 中科院回复:龙芯不是汉芯
- openssl在arm下的交叉编译
- 在计算机英语中 input的意思是,计算机英语词汇解释
- 快速截图工具——百度输入法的扩展功能
- MOOC上的excel技巧
- ObjectBox的探究
- SpringBoot2尚硅谷笔记
- 华为应用市场Android客户端,华为应用市场官方安卓最新版
- 如何取消掉计算机更新图标,本文演示win10电脑更新图标怎么去掉的具体操作方式...
- android百度地图定位跳转中心点,百度地图,拖动地图,定位marker固定在屏幕中心位置...
- Java中日志的使用
热门文章
- 机器学习-有监督-SVM
- Mysql多表查询笔记
- “互联网+”解决城市交通拥堵难题
- 微信小程序开发之路(一)
- Oozie JMS通知消息实现--根据作业ID来过滤消息
- Fedora 14安装飞信
- 恢复 outlook express中的附件按钮
- hdfs dfs -cat 出现No such file or directory
- nginx: [error] invalid PID number in /run/nginx.pid解决办法之一
- Possible missing firmware /lib/firmware/i915/bxt_guc_ver8_7.bin for module i915