`
jukyoc
  • 浏览: 13110 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

oracle rowid详解(转自http://117367462li.blog.163.com/blog/static/587176201011229351)

 
阅读更多
Oracle rowid 详解 

2010-12-22 09:35:18|  分类: Oracle |  标签:number  dbms_rowid  rowid  oracle  select   |字号 订阅
本文讨论的是关于oracle从8i开始引进object的概念后的rowid,即扩展(extended)的rowid:

1.       rowid的介绍

先对rowid有个感官认识:

SQL> select ROWID from Bruce_test where rownum<2;

ROWID
------------------ ----------
AAABnlAAFAAAAAPAAA
ROWID的格式如下:

数据对象编号        文件编号        块编号           行编号
OOOOOO             FFF                BBBBBB RRR

我们可以看出,从上面的rowid可以得知:
AAABnl 是数据对象编号
AAF是相关文件编号
AAAAAP是块编号
AAA 是行编号

怎么依据这些编号得到具体的十进制的编码值呢,这是经常遇到的问题。这里需要明白rowid的是基于64位编码的18个字符显示(数据对象编号(6) +文件编号(3) +块编号(6)+       行编号(3)=18位),其中
A-Z <==> 0 - 25 (26)
a-z <==> 26 - 51 (26)
0-9 <==> 52 - 61 (10)
+/ <==> 62 - 63 (2)

共64位,明白这个后,就可以计算出10进制的编码值,计算公式如下:
d * (b ^ p)
其中:b就是基数,这里就是64,p就是从右到左,已0开始的位置数
比如:上面的例子
文件号AAF,具体的计算应该是:
5*(64^0)=5;
0*(64^1)=0;
0*(64^2)=0;
文件号就是0+0+5=5
刚才提到的是rowid的显示方式:基于64位编码的18个字符显示,其实rowid的存储方式是:10 个字节即80位存储,其中数据对象编号需要32 位,相关文件编号需要10 位,块编号需要22,位行编号需要16 位,由此,我们可以得出:
32bit的object number,每个数据库最多有4G个对象
10bit的file number,每个对象最多有1022个文件(2个文件预留)
22bit的block number,每个文件最多有4M个BLOCK
16bit的row number,每个BLOCK最多有64K个ROWS

2.       rowid相关的有用的sql

最简单的基于rowid的显示方式得到的响应的64位编码对应值的sql:
select rowid ,
substr(rowid,1,6) "OBJECT",
substr(rowid,7,3) "FILE",
substr(rowid,10,6) "BLOCK",
substr(rowid,16,3) "ROW"
from TableName;

OWID              OBJECT       FILE   BLOCK        ROW
------------------ ------------ ------ ------------ ------
AAABc4AADAAAGLUAAA AAABc4       AAD    AAAGLU       AAA
AAABc4AADAAAGLUAAB AAABc4       AAD    AAAGLU       AAB
AAABc4AADAAAGLUAAC AAABc4       AAD    AAAGLU       AAC
AAABc4AADAAAGLUAAD AAABc4       AAD    AAAGLU       AAD
AAABc4AADAAAGLUAAE AAABc4       AAD    AAAGLU       AAE

通过dbms_rowid这个包,可以直接的得到具体的rowid包含的信息:
select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id ,dbms_rowid.rowid_row_number(rowid) num from bruce_t where rownum<5;

OBJECT_ID    FILE_ID   BLOCK_ID        NUM
---------- ---------- ---------- ----------
      5944          3      25300          0
      5944          3      25300          1
      5944          3      25300          2
      5944          3      25300          3

一些使用ROWID的函数
ROWIDTOCHAR(rowid) :将ROWID转换成STRING
CHARTOROWID('rowid_string') :将STRING转换成ROWID

另外,就是自己写的一些函数:(下面的函数是网友eygle提供)

create or replace function get_rowid

(l_rowid in varchar2)
return varchar2
is
ls_my_rowid     varchar2(200);         
rowid_type     number;         
object_number     number;         
relative_fno     number;         
block_number     number;         
row_number     number;

begin
dbms_rowid.rowid_info(l_rowid,rowid_type,object_number,relative_fno, block_number, row_number);         
ls_my_rowid := 'Object# is      :'||to_char(object_number)||chr(10)||
        'Relative_fno is :'||to_char(relative_fno)||chr(10)||
        'Block number is :'||to_char(block_number)||chr(10)||
        'Row number is   :'||to_char(row_number);
return ls_my_rowid ;
end;        

/

应用上面的函数如下:
SQL> select get_rowid(rowid), name from bruce_t;
GET_ROWID(ROWID)                                                                 NAME

-------------------------------------------------------------------------------- --------------------------------
Object# is      :5944                                                      BruceLau
Relative_fno is :3                                                              
Block number is :25300                                                          
Row number is   :0                                                              
Object# is      :5944                                                     MabelTang
Relative_fno is :3                                                              
Block number is :25300                                                          
Row number is   :1

ROWID:
    ROWID为该表行的唯一标识,是一个伪列,可以用在SELECT中,但不可以用INSERT, UPDATE来修改该值。
注意:ROWID的表指,普通表,cluster table, partition table, subpartition table, index, index partitions and subpartitions(注意:不包含index-organized tables).
    每个表Oracle都存在一个伪列ROWID,这个伪列可以用SELECT查看,但是不可以用INSERT, UPDATE来修改。你也不可以用DELETE来删除
ROWID列,Oracle使用ROWID列来建立内部索引。你可以引用ROWID的值,但ROWID并不存放在数据库中,你可以创建一个表包含ROWID数据类型,
但Oracle不保证该值是合法的rowids。用户必须确保该rowid值是真实合法的。
UROWID:
    UROWID(可以称为通用ROWID,逻辑ROWID): 表的行地址,表指的是index-organized tables。IOT中物理rowid是可能变化的,另外Oracle要依靠rowid来建立表的索引,所以对IOT表来物理rowid就不行了。Oracle以表的主键为基础引入UROWID,在物理rowid基础上建立了第二个索引。每一个逻辑rowid使用一个第二索引和一个物理推测(IOT中标识块的行)。
    UROWID支持逻辑和物理的rowids,列UROWID类型可以存储各种rowids, 从8.1以后的Oracle才有UROWID类型,它也可以用来保存以前的ROWID类型数据信息。
    更新IOT的主键可能导致ROWID改变,该行的UROWID也会改变。

Oracle使用rowid数据类型存储行地址,rowid可以分成两种,分别适于不同的对像

Physical rowids:存储ordinary table,clustered table,table partition and subpartition,indexe,index partition and subpartition

Logical rowids :存储IOT的行地址

另一种rowid类型叫universal rowed(UROWID),支持上述physical rowid和logical rowed,并且支持非oracle table,即支持所有类型的rowid,但COMPATIBLE必须在8.1或以上.

1.1 ROWID伪列

    每个表在oracle内部都有一个ROWID伪列,它在所有sql中无法显示,不占存储空间;它用于从表中查询行的地址或者在where中进行参照,一个例子如下:

    SELECT ROWID, last_name FROM employees;

    Oracle内部使用保留在ROWID伪列中的值构建索引结构

    再次强调一次,rowid伪列不存储在数据库中,它不是数据库数据,这是从database及table的逻辑结构来说的,事实上,在物理结构上,每行由一个或多个row pieces组成,每个row piece的头部包含了这个piece的address,即rowid.从这个意义上来说,rowid还是占了磁盘空间的.

   我们在创建表时,可以为列指定为rowid数据类型,但oracle并不保证列中的数据是合法的rowid值,必须由应用程序来保证,另外,类型为rowid的列需要6 bytes存储数据

1.2, physical rowids

  

只在行存在,它的物理地址rowid就不会变化,除非export/import,根据rowid可以直接定位到block去fetch数据,所以physical兼具有高稳定(stability)和高性能(performance)的特点.

这里要注意一点,对于clustered table来说,根据它的存储特点,在同一个block中的不同table的行可能具有同一个rowid;而nonclustered table,每一行或初始行片(initial row piece)都有唯一的rowid

要注意rowid的地址固定的特点,在一个block的某一行被delete并commit后,它占据的address可以被其它事务新insert的行重用.

Physical rowid可以是下面任一一种格式:

    1) Extended rowid

        使用表空间相关的数据块地址,8i及以上使用这种格式

      

2) Restricted rowid

   使用数据库范围的数据址地址,oracle 7或更早前的版本使用

1.2.1extened rowid

      扩展行地址是64编码的物理地址,编码字符是A-Z, a-z, 0-9, +,and/.

      由4部分组成OOOOOOFFFBBBBBBRRR (obj#file#block#row#)

     

      OOOOOO -–data object number

       FFF –-表空间相对的数据文件号

       BBBBBB –-块号

       RRR ---行号

       注意不是16进制表示

      SQL> select rowid,name from obj$ where rownum<=10;

ROWID             NAME

------------------ ------------------------------

AAAAASAABAAAAB6ABc ACCESS$

AAAAASAABAAAC1QAAK AGGXMLIMP

AAAAASAABAAAC1QAAL AGGXQIMP

AAAAASAABAAAGiRAAI ALERT_QT

AAAAASAABAAAGiRAAh ALERT_QUE

AAAAASAABAAAGujAAo ALERT_QUE$1

AAAAASAABAAAGujAAp ALERT_QUE$1

AAAAASAABAAAGiRAAf ALERT_QUE_N

AAAAASAABAAAGiRAAe ALERT_QUE_R

AAAAASAABAAAGiRAAG ALERT_TYPE

我们可以使用dbms_rowid从extened rowid中抽取各部分信息,或者将extened rowid转换成restricted rowed,详细的信息参见sys.dbms_rowid的规范

#根据rowid抽块对像编号

SQL> select dbms_rowid.rowid_object('AAAAASAABAAAGiRAAG') obj# from dual;

     OBJ#

----------

       18

#根据rowid抽取表空间相对文件号

SQL> select dbms_rowid.rowid_relative_fno('AAAAASAABAAAGiRAAG') rfile# from dual;

    RFILE#

----------

        1

#根据rowid抽取块号

SQL> select dbms_rowid.ROWID_BLOCK_NUMBER('AAAAASAABAAAGiRAAG') block# from dual;

   BLOCK#

----------

    26769

#根据rowid抽取行号

SQL> select dbms_rowid.rowid_row_number('AAAAASAABAAAGiRAAG') row# from dual;

     ROW#

----------

        6

#将extended rowid转换成为restricted rowid

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

RESTRICTED_ROWID

------------------

00006891.0006.0001

1.2.2restricted rowid

限制地址行号与扩展地址行号编码方式不一样,它在内部使用二进制方式表示,当用select查询时,会转换成varchar2/16进制的混合形式,它的组织方式如下:

BBBBBBBB.RRRR.FFFF (block#.row#.file#)

注意,这里的文件号是绝对文件号,而extended rowid中是相对文件号(相对表空间)

Restricted rowid中不再有object number,因为从绝对文件号可以唯一确定数据块

样例可以参考前面的00006891.0006.0001

    另外请注意,块中的行号是从0开始

除了用dbms_rowid来抽取rowid的不同部分外,也可以用substr

#extended rowid

SQL> SELECT ROWID,

2007-02-01 15:19:28
2         SUBSTR(ROWID,1,6) "OBJECT",
3         SUBSTR(ROWID,7,3) "FIL",
4         SUBSTR(ROWID,10,6) "BLOCK",
5         SUBSTR(ROWID,16,3) "ROW"
6   from obj$ where rownum<=5;

ROWID              OBJECT       FIL    BLOCK        ROW
------------------ ------------ ------ ------------ ------
AAAAASAABAAAAB6AAa AAAAAS       AAB    AAAAB6       AAa
AAAAASAABAAAAB6AAu AAAAAS       AAB    AAAAB6       AAu
AAAAASAABAAAAB6AAF AAAAAS       AAB    AAAAB6       AAF
AAAAASAABAAAAB6AAv AAAAAS       AAB    AAAAB6       AAv
AAAAASAABAAAAB6AAZ AAAAAS       AAB    AAAAB6       AAZ

#restricted rowid
SQL> SELECT ROWID,
2         SUBSTR(ROWID,15,4) "FILE",
3         SUBSTR(ROWID,1,8) "BLOCK",
4         SUBSTR(ROWID,10,4) "ROW"
5   from obj$ where rownum<=5;

ROWID              FILE     BLOCK            ROW
------------------ -------- ---------------- --------
AAAAASAABAAAAB6AAa 6AAa     AAAAASAA         AAAA
AAAAASAABAAAAB6AAu 6AAu     AAAAASAA         AAAA
AAAAASAABAAAAB6AAF 6AAF     AAAAASAA         AAAA
AAAAASAABAAAAB6AAv 6AAv     AAAAASAA         AAAA
AAAAASAABAAAAB6AAZ 6AAZ     AAAAASAA         AAAA

请注意extented rowid与restricted rowid的编码方式不一样,大家不能拿两种不同编码方式的组件作比较,比如AAAAASAABAAAAB6AAa 这行的File#在两种方式下是有不同的值,表示不同的意义,没有可比性.

下面的语句可以查看表的数据分布在几个文件中
SQL> SELECT COUNT(DISTINCT(SUBSTR(ROWID,7,3))) "FILES" FROM BOSSSTATSDATA;

     FILES
----------
        17
#下面验证bossstatsdata的数据确实分布在17个文件中
SQL> select count(file_name) from dba_data_files where TABLESPACE_NAME= (select TABLESPACE_NAME from user_tables where table_name='BOSSSTATSDATA');

COUNT(FILE_NAME)
----------------
              17

总结Rowid的使用场景
1) 构建索引结构, 每个key都有一个rowid指向相应的表行
2) rowid是访问表行的最快的方法
3) rowid可用于观察表数据是怎样组织的
4) rowid是表行的唯一标识符

在任何DML中使用rowid时,应该注意确保相关的行不会改变物理地址(不会被export/import,delete)

1.3 logical rowids
    用于表达IOT行地址的Logical rowid存储在索引的叶子节点中,会随着索引entry的insert在块内或块间移动,所以,它不是基于物理地址而是基于primary key的标识符,所以取名叫logcial rowid
Oracle使用logical rowids来构建IOT的secondary indexes
由于在实际的应用中很少会使用到IOT这种对像,关于logical rowid更详细的描述可以参见<<concepts>>中相关章节
Part IV Oracle Database Application Development
26 Native Datatypes
Overview of ROWID and UROWID Datatypes

1.4 非oracle table中的rowid
在非oracle系统中,不同的系统有不同的rowid格式,并且,不能使用前述标准的rowid到varchar2/16进制的转换方法, 所以,在这种情况下,应用程序可以使用rowid数据类型,不过要使用非标准的转换方法 (最长256bytes的16进制)
非oracle 系统中的rowid也能存储在UROWID数据类型中
分享到:
评论

相关推荐

    DB2兼容模式设置文档

    ### DB2兼容模式设置文档详解 #### 一、概述 本文档主要介绍如何将IBM DB2数据库设置为Oracle兼容模式,并列举了一些关键的验证点,包括数据类型、SQL语法特性的差异、公共视图和存储过程等。通过这些验证点,可以...

    oracle_SQL中ROWID与ROWNUM的使用

    NULL 博文链接:https://newleague.iteye.com/blog/1094101

    bootstrap-table 表内行拖放所需js/css及实例

    var rowId = $(this).data('id'); newOrder.push(rowId); }); // 保存新顺序到服务器 saveNewOrderToServer(newOrder); } }); }); ``` `saveNewOrderToServer(newOrder)`是假设的一个函数,实际应用中你...

    Jquery 实现列的拖动 jquery grid

    &lt;script src="https.//code.jquery.com/ui/1.12.1/jquery-ui.min.js"&gt;&lt;/script&gt; &lt;script src="path/to/jquery.jqGrid.min.js"&gt;&lt;/script&gt; ``` 接下来,我们需要创建一个HTML表格作为jQuery Grid的基础,并配置相应的...

    Sqlite数据库使用demo

    Sqlite数据库是一个轻量级的、开源的、自包含的关系型数据库管理系统,广泛应用于嵌入式系统和移动应用中。这个“Sqlite数据库使用demo”是针对C语言环境设计的一个示例,它演示了如何在C++项目中集成并操作SQLite...

    Oracle数据库rowid深入探析.pdf

    "Oracle数据库rowid深入探析" Oracle数据库rowid是Oracle数据库中一个重要的概念,也是Oracle DBA考试中一个重要的知识点。rowid是Oracle数据库中的一种伪列,它可以唯一地标识表中的每一行。伪列类似于数据表的列...

    山东大学新版数据库实验题目

    【山东大学新版数据库实验题目】是一份针对2014年数据库课程的实验指导文档,旨在帮助学生熟悉Oracle数据库管理系统。实验主要目的是让学生通过实际操作掌握数据库的基本操作和概念,如SQL语言的运用、数据查询、表...

    mysql虚拟了一个rowid(类似跟oracle的rowid)--SQL语句.sql

    mysql虚拟了一个rowid(类似跟oracle的rowid)--SQL语句

    Oracle学习笔记(rownum和rowid)

    Oracle学习笔记(rownum和rowid),有具体的代码案例讲解rownum和rowid

    Oracle sql语句多表关联查询

    Oracle SQL 语句多表关联查询 Oracle SQL 语句多表关联查询是数据库管理系统中的一种常见查询方式,它可以从多个表中检索数据,满足业务需求。本文将详细介绍 Oracle SQL 语句多表关联查询的知识点,包括字符串和...

    最全的oracle常用命令大全.txt

    ORACLE常用命令 一、ORACLE的启动和关闭 1、在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a、启动ORACLE系统 oracle&gt;svrmgrl SVRMGR&gt;connect internal SVRMGR&gt;startup ...

    Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(一)

    谢谢大家的支持,我会陆续上传相关电子书 由于体积较大,本书分两卷压缩,请都下载完再解压! Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(一) ... 第40章 转换rowid  第41章 其他常用包 习题答案

    oracle执行计划详解

    Oracle 执行计划详解是数据库管理系统中一个非常重要的概念。本文将详细介绍 Oracle 执行计划的相关概念、访问数据的存取方法、表之间的连接等内容,并对总结和概述,以便于理解和记忆。 一、相关的概念 1. Rowid ...

    《Oracle 10g入门与提高》第6章:PL、SQL程序设计.pptx

    PL/SQL 是 Oracle 数据库提供的过程化语言,它是 ANSI 标准 SQL 的扩展,专为数据库操作设计。它的主要特点是能够结合 SQL 语句,实现更复杂的数据处理逻辑。 在 PL/SQL 中,变量的声明遵循一定的规则:变量名必须...

    Oracle中用Rowid查找和删除表中的重复记录

    ### Oracle中用Rowid查找和删除表中的重复记录 在Oracle数据库管理中,处理重复记录是一项常见的需求,尤其是在数据量较大的情况下。本文将详细介绍如何利用Rowid这一特性来有效地查找和删除表中的重复记录。 ####...

    数据列表组件 jqGrid 二次封装

    **jqGrid 数据列表组件二次封装详解** jqGrid 是一个基于 jQuery 的强大表格插件,用于展示和管理数据,提供丰富的功能如排序、分页、编辑等。本篇文章将深入探讨如何对 jqGrid 进行二次封装,以适应个性化的需求,...

    利用rowid快速在线更新海量数据

    **ROWID** 是 Oracle 数据库中一个非常重要的概念,它是一种特殊类型的列,用于唯一标识表中的一行数据。ROWID 的格式通常包含数据对象号 (Data Object Number)、相对文件号 (Relative File Number)、块号 (Block ...

    oracle PL-SQL 基础

    根据提供的文件信息,我们可以深入探讨Oracle PL/SQL的基础知识点,包括其历史背景、优势、基本结构、以及变量的定义和使用等内容。 ### PL/SQL的历史 PL/SQL(Procedural Language for SQL)是一种专门为Oracle...

    《Oracle 10g入门与提高》第6章:PL、SQL程序设计 .pptx

    《Oracle 10g入门与提高》第6章主要涵盖了PL/SQL程序设计的基础和核心概念,这包括了变量声明、数据类型、表达式、程序块结构、控制结构、游标、过程与函数、触发器以及异常处理。下面将详细阐述这些知识点。 6.1 ...

Global site tag (gtag.js) - Google Analytics