文档章节

Oracle中的rowid

小强斋太
 小强斋太
发布于 2016/11/09 20:05
字数 1335
阅读 10
收藏 0

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

ROWID是ORACLE中的一个重要的概念。用于定位数据库中一条记录的一个相对唯一地址值。通常情况下,该值在该行数据插入到数据库表时即被确定且唯一。ROWID它是一个伪列,它并不实际存在于表中。它是ORACLE在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列。所以根据一行数据的ROWID能找到一行数据的物理地址信息。从而快速地定位到数据行。数据库的大多数操作都是通过ROWID来完成的,而且使用ROWID来进行单记录定位速度是最快的。

要理解索引,必须先搞清楚ROWID。

B-Tree索引的每个索引条目具有两个字段。第一个字段表示索引的键值,对于单列索引来说是一个值;而对于多列索引来说则是多个值组合在一起的。第二个字段表示键值所对应的记录行的ROWID。所以索引能加快查询速度!

索引值→ROWID->将ROWID换算成一行数据的物理地址->得到一行数据

一、ROWID的格式:

clip_image001

第一部分6位表示:该行数据所在的数据对象的 data_object_id
第二部分3位表示:该行数据所在的相对数据文件的id;
第三部分6位表示:该数据行所在的数据块的编号;
第四部分3位表示:该行数据的行的编号;

索引就是保存了rowid后三个部分的信息。索引是物理存在的,而rowid是伪列。所以索引可以用来快速地定位到数据行。

data_object_id

下面以SAKILA数据库的ACTOR表为例

这里我们要注意将 data_object_id  object_id 区分开来,前者是oracle为它的每一个对象唯一分配的id,而后者与表ACTOR对应的“段”有关,是存放表tt的段的id,也就是与存放表tt中数据的物理位置有关:

select owner,object_id,data_object_id,status from dba_objects where object_name='ACTOR';

clip_image002

alter table ACTOR move tablespace users;

select owner,object_id,data_object_id,status from dba_objects where object_name='ACTOR';

clip_image003

我们看到当表ACTOR move到了users表空间时,段发生了改变,物理位置发生了变化,从而 DATA_OBJECT_ID 也发生了变化。我们知道表是存放在“表段”中的,索引是存放在“索引段”中的。DATA_OBJECT_ID就是表示存放数据的“数据段对象的id”

相对文件编码

关于相对文件编码和绝对文件编号:相对文件id是指相对于表空间,在表空间唯一,绝对文件是指相当于全局数据库而言的,全局唯一;

select file_name,file_id,relative_fno from dba_data_files;

clip_image004

rowid采用64进制来编码

编码方法是:A~Z表示0到25;a~z表示26到51;0~9表示52到61;+表示62;/表示63;刚好64个字符。

Base64编码表

码值 字符   码值 字符   码值 字符   码值 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

二、使用rowid访问数据的执行计划

SELECT t.*, ''||t.ROWID FROM "SAKILA"."ACTOR" t;

clip_image005

EXPLAIN PLAN FOR                                                                                         
select * FROM ACTOR where rowid='AAAYEVAAJAAAACrAAA';  
select * from table(DBMS_XPLAN.DISPLAY)

image

三、例子:如何从rowid计算得到obj#,rfile#,block#,row#

我们演示一下具体的计算方法:

SELECT t.*, ''||t.ROWID FROM "SAKILA"."ACTOR" t;

clip_image005

表sakila的 data_object_id 为 AAAYEVAAJAAAACrAAA的前6位:AAAYEV,那么我们来计算一下 AAAYEV的值到底是多少:

查询Base64编码表

码值 字符
0 A
24 Y
4 E
21 V

select 24 * 64 * 64 + 4 * 64 + 21 from dual;

AAAYEV=24 * 64 * 64 + 4 * 64 + 21=98581

然后我们查询字典表,看两种方法得到的值是否相等:

select owner,object_id,data_object_id,status from dba_objects where object_name='ACTOR';

clip_image003[1]

我们看到通过rowid计算得到的data_object_id和通过字典表查到的值相等!

表ACTOR的相对文件编号为 AAAYEVAAJAAAACrAAA 的中的 AAJ,显然查表可知 AAJ= 9;

我们在再来查询字典表:

clip_image006

可以看到字典表显示relative_fno为9的数据文件为C:\APP\ORACLE\ORADATA\ORCL\PDBORCL\SAMPLE_SCHEMA_USERS01.DBF

查询当前数据库中的users表空间和对应的数据文件

select file_name,tablespace_name from dba_data_files;

clip_image007

两者结果一致。

而我们前面执行过:alter table ACTOR move tablespace users;所以两种方式得到的结果是一致的。

表ACTOR中的第一行数据存放的block的编号为 AAAYEVAAJAAAACrAAA 中的 AAAACr,而AAAACr =2*64+43=171
表ACTOR中的第一行数据存放的行的编号为AAAYEVAAJAAAACrAAA 中的 AAA,显然值为0,即第一行。

我们也可以通过Oracle提供的存储过程来计算出上面的值:

SELECT

dbms_rowid.rowid_object (ROWID) data_object_id,

dbms_rowid.rowid_relative_fno (ROWID) relative_fno,

dbms_rowid.rowid_block_number (ROWID) block_no,

dbms_rowid.rowid_row_number (ROWID) row_no

FROM

ACTOR;

clip_image008

显然这个结果和我们手动计算的结果是一致的。

参考

Oracle中的rowid学习

oracle中rowid的用法

本文转载自:http://www.cnblogs.com/xqzt/p/4449184.html

小强斋太
粉丝 0
博文 181
码字总数 0
作品 0
广州
私信 提问
加载中

评论(0)

Rowid和Rownum的区别

Rowid和Rownum对于数据库开发人员来说基本很少用到,因为在企业数据库开发中大多都是进行数据批处理,但是对于其他数据库人员来说还是会用到的。 rowid和rownum都是虚列,但含义完全不同。r...

wangergui
2017/02/23
0
0
mysql与oracle去重方案的异同,mysql处于学习阶段不太熟悉,最后有两个解决不了,求大神帮忙补充上

去重查询语句 oracle: select * from table1 a where rowid in (select max(rowid) from table1 b where a.id = b.id) mysql: select a.id,* from table1 a group by a.id 查询重复的语句 or......

混分小菜鸟
2015/03/20
347
2
《Oracle Database Concepts 11g Release 2》读书笔记(2)...

Table(P36-P50) 1. 定义 Table 是 oracle中数据的基本组成单位. Oracle 中定义了两种类型的 Table: 1) Relation Table 最常用的 table 类型,列由基本数据类型组成. 每个 Realation Table 是以...

sailtseng
2012/06/07
123
0
复习巩固:oracle如何实现去重和分页

一:oracle实现去重: user数据表: 分两步:1.查询重复数据 2.删除重复数据 1.查询重复数据: 在oracle中实现查询重复数据,可以借助于rowid这个伪列。oracle中每个表物理上都存在一个rowid...

osc_qg4dad59
2019/08/13
2
0
Oracle 优化器_访问数据的方法_单表

  Oracle 在选择执行计划的时候,优化器要决定用什么方法去访问存储在数据文件中的数据。我们从数据文件中查询到相关记录,有两种方法可以实现:1.直接访问表记录所在位置。2.访问索引,拿...

osc_6nds72mv
2019/09/02
4
0

没有更多内容

加载失败,请刷新页面

加载更多

图解!24张图彻底弄懂九大常见数据结构! (转载)

挺不错的一篇文章,图解很清晰,转载一下: 点击前往

庭前云落
46分钟前
34
0
安装docker

1.添加依赖: yum install -y yum-utils device-mapper-persistent-data lvm2 2、添加软件源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.r......

muoushi
59分钟前
27
0
网络地址转换 NAT 配置

理解 NAT 网络地址转换的原理及功能 掌握静态 NAT 的配置,实现局域网访问互联网 实验背景 你是某公司的网络管理员,欲发布公司的 WWW 服务。现要求将内网 Web 服务器 IP地址映射为全局 IP 地...

老孟的Linux私房菜
今天
39
0
别在 Java 代码里乱打日志了,这才是正确的打日志姿势!

使用slf4j 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。 实现方式统一使用: Logback框架 打日志的正确方式 什么时候应该打日志 当你遇到问题的时候,只能通过debug功能来...

码农突围
今天
44
0
spring boot 设置任务调度线程池大小和线程前缀

编辑文件application.properties,加入如下: spring.task.scheduling.pool.size =10spring.task.scheduling.thread-name-prefix = sche_prefix-...

jingshishengxu
今天
26
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部