热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

详解Oraclerowid之来龙去脉

nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd

rowid 从字面解释为行标识。在Oracle中,通过rowid定位记录是最快和最有效的方式。那么rowid在oracle中是怎样定位记录的哪?并且它为什么是最有效的方式?带着这些问题,让我们一步一步揭开rowid的神秘面纱。

首先,我们看一下怎样获取表中记录的rowid:通过rowid伪列

SQL> select rowid,id from ppp;

ROWID      ID
------------------ ----------
AAAS5VAAEAAAAemAAC    3
AAAS5VAAEAAAAemAAD    9
AAAS5VAAEAAAAemAAE    7

我们知道,oracle在逻辑上有多个表空间构成,每个表空间又包含多个数据文件,数据文件对应操作系统上的文件(asm情况类似,不做考虑),而数据文件又包含若干数据块,我们的表记录就是存储在数据块中。因此,如果我们知道某条记录所存储的数据文件、数据块和在块中的偏移量,就可以非常快速的读取记录并展现给用户。rowid恰恰可以帮助我们实现这一点,因为在rowid字符串中包含了数据文件、数据块和记录在块中地址的信息。

在8i之前,oracle采用受限的rowid(Restricted rowid),受限rowid是针对整个数据库范围的rowid,由三部分构成,即数据文件编号,块编号和记录在块内的偏移量。受限rowid占用6个字节的存储空间,其中数据文件编号占用10bit,数据块编号占用22bit,偏移量即记录在数据块中的行号占用16bit。从这里我们也可看出在8i之前的数据库中:

每个数据库最多包含1022个文件(2个文件预留)

每个文件最多可以有4m个数据块

每个块最多可以存储64k条记录。

受限的rowid在底层存储使用二进制格式,展现时采用varchar2和16进制混合的形式:BBBBBBBB.RRRR.FFFF (block#.row#.file#),如:

SQL> select dbms_rowid.rowid_to_restricted('AAAS5VAAEAAAAemAAE',0) from dual;

DBMS_ROWID.ROWID_T
------------------
000007A6.0004.0004

到目前为止,情况都是非常明朗的,但是随着oracle的发展,我们需要突破某些限制,例如单个数据库最多1022个数据文件的限制,同时我们还要保持数据库的向后兼容性以及为数据库的某些特性如表空间迁移做出充分的考虑。在这种情况下,仅仅只是通过扩展受限rowid的存储长度是不够的,例如我们将数据文件编号占用的存储空间从10bit扩增到20bit,虽然可以在单个数据库中存储更多的数据文件,但是却增加了向后兼容的难度(因为物理存储格式发生了变化),而且在使用表空间迁移时,如果从旧版本迁移到8i之后的版本,我们需要扫描整个迁移的表空间来修改其中存储的rowid信息,这显然与表空间迁移的初衷(通过拷贝文件和导入元数据信息来导入表空间)是相违背的。

为了达到以上种种目的,oracle引入了相对文件号的概念,这种方法的主要思想是改变之前rowid中数据文件编号是参考整个数据库范围i的事实,将其参考的范围改为表空间,即文件编号为4的文件不再是数据库中编号为4的数据文件,而是某个表空间中编号为4的数据文件。这样我们便可以在不改变物理存储格式的情况下(仅仅是我们在解析rowid内容时的处理逻辑发生了变化,如将前10bit解析为表空间相对文件号rfn,而不是文件号file_id,然后通过数据字典视图将),进行数据库的扩容等等。

SQL> select file_id,relative_fno from dba_data_files;

  FILE_ID RELATIVE_FNO
---------- ------------
  4      4
  3      3
  2      2
  1      1
  5      5
  6      6
  7      6
  8      8
  9      9

从这里我们看到file_id和relative_fno是一一相等的,其实不然,在数据文件数量没有超过1022个时,oracle数据库尽量保持file_id和relative_fno的相同,在超过1022个数据文件后,oracle就会保证在整个数据库内file_id是唯一的,在单个表空间中relative_fno是唯一的。

那么这时就会存在一个问题,不同表空间中的具有相同相对文件号数据文件oracle是怎样区分开来的那?为了解决这个问题,oracle在原有6byte rowid的基础上又添加了DATA_OBJECT_ID的信息,构成扩展rowid,即扩展rowid由四部分构成:data_object_id,rfn,block#,row#。通过data_object_id 和数据字典视图的结合,oracle可以非常快速的将rfn转换为file_id,从而也就可以准确的进行行定位。

我们以11g中索引的存储格式为例,总结如下:

普通表:

--普通索引:6字节
row#0[8020] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 02
col 1; len 6; (6):  01 00 05 e3 00 00
row#1[8008] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 05 e3 00 01
row#2[7996] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 04
col 1; len 6; (6):  01 00 05 e3 00 02

--全局分区:
row#0[8020] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 02
col 1; len 6; (6):  01 00 05 e3 00 00
row#1[8008] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 05 e3 00 01
row#2[7996] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 04
col 1; len 6; (6):  01 00 05 e3 00 02
----- end of leaf block dump -----

分区表:

--全局分区:分区  10字节
col 0; len 2; (2):  c1 02
col 1; len 10; (10):  00 01 2e 55 01 00 07 a6 00 00
row#1[7984] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 04
col 1; len 10; (10):  00 01 2e 55 01 00 07 a6 00 02
row#2[7968] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 08
col 1; len 10; (10):  00 01 2e 55 01 00 07 a6 00 04
row#3[7952] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 0a
col 1; len 10; (10):  00 01 2e 55 01 00 07 a6 00 03

---本地索引:6字节
row#0[8020] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 04
col 1; len 6; (6):  01 00 07 a6 00 02
row#1[8008] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 08
col 1; len 6; (6):  01 00 07 a6 00 04
row#2[7996] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 0a
col 1; len 6; (6):  01 00 07 a6 00 03
----- end of leaf block dump -----

更多详情见请继续阅读下一页的精彩内容: 2013-11/92826p2.htm

Oracle入门基础教程:rowid详解 2012-10/73265.htm

Oracle 中ROWNUM用法总结,ROWNUM 与 rowid 区别 2012-07/66121.htm

rowid走索引之嫌疑犯抓获 2012-06/62302.htm

Oracle利用rownum和rowid分页 2012-04/58301.htm


推荐阅读
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 在很多数据库中都存在一个自动增长的列,如果现在要想在oracle中完成自动增长的功能,则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。语法:CREAT ... [详细]
  • FineReport平台数据分析图表显示部分系列接口的应用场景和实现思路
    本文介绍了FineReport平台数据分析图表显示部分系列接口的应用场景和实现思路。当图表系列较多时,用户希望可以自己设置哪些系列显示,哪些系列不显示。通过调用FR.Chart.WebUtils.getChart("chartID").getChartWithIndex(chartIndex).setSeriesVisible()接口,可以获取需要显示的系列图表对象,并在表单中显示这些系列。本文以决策报表为例,详细介绍了实现方法,并给出了示例。 ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了一个误删Oracle数据文件导致数据库无法打开的问题,并提供了解决方式。解决方式包括切换到mount状态、离线删除报错的数据文件等。 ... [详细]
author-avatar
mobiledu2502929447
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有