ORACLE ROWID

Oracle通过rowid来唯一标识行,Rowid并不物理存储在数据库中,而是从存储数据的文件和块中推断出来的。

Oracle Database uses a rowid to uniquely identify a row. A rowid is not physically stored in the database, but is inferred from the file and block on which the data is stored. pseudocolumn behaves like a table column, but is not actually stored in the table.

SQL> SELECT ROWID FROM employees WHERE employee_id = 100;

ROWID

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

AAAPecAAFAAAABSAAA

  • Base64编码

Rowid是把行每行的物理地址进行base64编码的结果

An extended rowid includes a data object number. This rowid type uses a base 64 encoding of the physical address for each row. The encoding characters are A-Z, a-z, 0-9, +, and /.

不论是文本还是二进制数据(如图片,视频)都是以01存储的,但展示时文本可以通过特定的编码解码后显示有实际意义的字符。而二进制数据也有特定编码,主要用于将二进制数据转换为字符用于传输,因为对它们编码后无实际意义,即不具有可读性,使用时需要再解码。

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一。

Base 64 Encoding的编码原理是把每3个8Bit的字节转换为4个6Bit的字节(3 x 8 = 4 x 6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节。不足3个的byte,根据具体规则决定是否填充。

6bit意味着总共有2^6即64种情况,与base64的字符表可以一一对应:

A~Z表示0到25;a~z表示26到51;0~9表示52到61;+表示62;/表示63

假设我们有三个字节的数据,byte[] {1, 2, 3},用二进制表示为:

00000001 | 00000010 | 00000011

依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

000000 | 010000 | 001000 | 000011

转换为十进制为 0 | 16 | 8 | 3,对照上面的表,编码后的文本为 AQID

既然Base 64 Encoding将每三个字节转换为四个字符,那如果一幅图片的字节数不能被3整除该怎么办?

如果剩余一个字节,该字节同样被转换为四个字符。第一个6 bit转换成一个字符,接下来2 bit转换成一个字符(注意这里是向右添加0),最后添加两个=字符。

假设我们有四个字节的数据,byte[] {1, 2, 3, 4},用二进制表示为:

00000001 | 00000010 | 00000011 | 00000100

依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

000000 | 010000 | 001000 | 000011 | 000001 | 000000

转换为十进制为 0 | 16 | 8 | 3 | 1 | 0,对照上面的表,编码后的文本为 AQIDBA==

如果不能被3整除,而余下两个字节,编码方式类似剩余一个字节,同样是转换成四个字符,最后一个字符用=。

假设我们有五个字节的数据,byte[] {1, 2, 3, 4, 5},用二进制表示为:

00000001 | 00000010 | 00000011 | 00000100 | 00000101

依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

000000 | 010000 | 001000 | 000011 | 000001 | 000000 | 010100

转换为十进制为 0 | 16 | 8 | 3 | 1 | 0 | 20,对照上面的表,编码后的文本为 AQIDBAU=

ROW组成

OOOOOOFFFBBBBBBRRR, with the format divided into the following components:

第一部分6位:该行数据所在的数据对象,即db_objects的data_object_id

The data object number identifies the segment  

Schema objects in the same segment, such as a table cluster, have the same data object number.

第二部分3位:该行数据所在的相对数据文件的id, 即dba_data_files的RELATIVE_FNO

The tablespace-relative data file number identifies the data file that contains the row

第三部分6位:该数据行所在的数据块的编号; 即DBA_EXTENTS的block_id

The data block number identifies the block that contains the row. Block numbers are relative to their data file, not their tablespace. Thus, two rows with identical block numbers could reside in different data files of the same tablespace.

第四部分3位:该行数据的行的编号;

The row number identifies the row in the block (row AAA in the sample query).

After a rowid is assigned to a row piece, the rowid can change in special circumstances. For example, if row movement is enabled, then the rowid can change because of partition key updates, Flashback Table operations, shrink table operations, and so on. If row movement is disabled, then a rowid can change if the row is exported and imported using Oracle Database utilities.

测试:

SELECT ROWID FROM ACTOR where rownum<2;   -- AAAYEVAAJAAAACrAAA

第一部分: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';

可发现它的data_object_id正是98581

第二部分 AAJ,显然查表可知 AAJ= 9,可查看具体使用表空间及文件:

select TABLESPACE_NAME, FILE_NAME,RELATIVE_FNO from dba_data_files;   

第三部分:AAAACr,AAAACr =2*64+43=171

select segment_name, block_id from DBA_extents where segment_name='ACTOR';

第四部分:AAA,显然值为0,即第一行

通过函数查看:

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;

DATA_OBJECT_ID RELATIVE_FNO   BLOCK_NO     ROW_NO

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

         98581        9           171          0

(三)ROWID分类

rowid 分为extended rowid 和 restricted rowied.

1. Restricted ROWID

Internally, the ROWID is a structure that holds information that the database server needs to access a row. The restricted internal ROWID is 6 bytes on most platforms.

Each restricted rowid includes the following data:

Datafile identifier

Block identifier

Row identifier

The restricted ROWID pseudo column is returned to client applications in the form of an 18-character string with a hexadecimal encoding of the datablock, row, and datafile components of the ROWID.

2. Extended ROWID

The extended ROWID datatype includes the data in the restricted rowid plus a data object number. The data object number is an identification number assigned to every database segment. The extended internal ROWID is 10 bytes on most platforms.

Data in an extended ROWID pseudo column is returned to the client application in the form of an 18-character string (for example, "AAAA8mAALAAAAQkAAA"), which represents a base 64 encoding of the components of the extended ROWID in a four-piece format, OOOOOOFFFBBBBBBRRR. Extended rowids are not available directly. You can use a supplied package, DBMS_ROWID, to interpret extended rowid contents. The package functions extract and provide information that would be available directly from a restricted rowid as well as information specific to extended rowids.

扩展的ROWID 在磁盘上需要10 个字节的存储空间,并使用18个字符来显示。

在内部,存储的10个字节(bytes),即80位(bit)又按如下规则进行划分:

  1. 数据对象编号需要32 bit
  2. 相关文件编号需要10 bit
  3. 块编号需要22 bit
  4. 行编号需要16 bit

在oracle 8以前,一个rowid占用6个字节大小的存储空间(10bit file#+22bit block#+16bit row#), rowid格式为:BBBBBBBB.RRRR.FFFF。BRF分别表示block,row,file

在oracle 8以后,rowid的存储空间扩大到了10个字节(32bit object#+10bit rfile#+22bit block#+16bit row#),文件号仍然用10位表示,只是不再需要置换,为了向后兼容,同时引入了相对文件号(rfile#),所以从Oracle7到Oracle8,Rowid仍然无需发生变化. 

rowid这样改变之后,数据库中数据库文件个数的限制从整个数据库最多只能有的2^10-2=1022个数据文件(去掉全0和全1),变为了每个表空间中可以最多有2^10-2个数据文件。所以说,数据库能支持的数据文件最大数是受rowid的长度限制的。 

可以使用dbms_rowid.rowid_type判断rowid是哪种类型,返回值为0表示restricted,为1表示extened: select dbms_rowid.rowid_type(rowid) from t1 where rownum<2;

可以使用dbms_rowid.rowid_to_extended及dbms_rowid.rowid_to_restricted进行转化,用时再查

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值