http://www.hzoes.com/ rowid與rownum不一樣
,(rownum不能以任何表的名稱作為字首, 和*一起使用的時候,
*前面必須加表名或者表的別名。)rowid前面可以加表名或者表別名,可以向其他普通列一樣使用。
本文討論的是關於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更詳細的描述可以參見<>中相關章節
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資料型別中
作者“jukyoc”
如何用rowid分頁
--普通寫法(顯示1-50頁)
select id, nick, auction_url, gmt_create
from (select id, nick, auction_url, gmt_create, rownum linenum
from (select id, nick, auction_url, gmt_create
from activity_pepsi_dream t
where status = 0
order by t.GMT_CREATE desc) r
WHERE rownum <= 50)
WHERE linenum >= 1
--rowid寫法
select
t2.id,
t2.nick,
t2.auction_url,
t2.gmt_create
from (select rid
from (select r.rid, rownum linenum
from (select
rowid rid
from activity_pepsi_dream t
where status = 0
order by t.GMT_CREATE desc) r
WHERE rownum <= 50)
WHERE linenum >=1) t1,
activity_pepsi_dream t2
where t1.rid = t2.rowid
效能比較:
---查詢第一頁普通寫法要比rowid寫法要快
---隨著翻頁次數的增多,普通寫法需要回表的記錄越來越多,效能下降很快。比如你要看200-250條的記錄,這時候普通寫法需要回表250條記錄,而rowid寫法只要會標200-250區間中的這50條記錄
rowid 寫法最佳化的情況:
--第一層必須都在索引中掃描,不回表
--第二三層找到滿足條件的rowid
--最後根據rowid去回表找到記錄
總結:關鍵就是oracle 的 rowid 屬性可以最快速度的尋找到該行的資料,並且固定,不需要回表操作。
。
<!-- 正文結束 -->
本文討論的是關於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更詳細的描述可以參見<
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資料型別中
作者“jukyoc”
如何用rowid分頁
--普通寫法(顯示1-50頁)
select id, nick, auction_url, gmt_create
from (select id, nick, auction_url, gmt_create, rownum linenum
from (select id, nick, auction_url, gmt_create
from activity_pepsi_dream t
where status = 0
order by t.GMT_CREATE desc) r
WHERE rownum <= 50)
WHERE linenum >= 1
--rowid寫法
select
t2.id,
t2.nick,
t2.auction_url,
t2.gmt_create
from (select rid
from (select r.rid, rownum linenum
from (select
rowid rid
from activity_pepsi_dream t
where status = 0
order by t.GMT_CREATE desc) r
WHERE rownum <= 50)
WHERE linenum >=1) t1,
activity_pepsi_dream t2
where t1.rid = t2.rowid
效能比較:
---查詢第一頁普通寫法要比rowid寫法要快
---隨著翻頁次數的增多,普通寫法需要回表的記錄越來越多,效能下降很快。比如你要看200-250條的記錄,這時候普通寫法需要回表250條記錄,而rowid寫法只要會標200-250區間中的這50條記錄
rowid 寫法最佳化的情況:
--第一層必須都在索引中掃描,不回表
--第二三層找到滿足條件的rowid
--最後根據rowid去回表找到記錄
總結:關鍵就是oracle 的 rowid 屬性可以最快速度的尋找到該行的資料,並且固定,不需要回表操作。
。
相關文章
- 【oracle rowid與rownum的使用與區別 】Oracle
- ROWID與ROWNUM的簡介與對比
- Oracle中rownum與rowid使用上的問題Oracle
- rowid和rownum的區別
- oracle中rownum和rowid的區別Oracle
- 不一樣的HTTP快取體驗HTTP快取
- rownum和rowid,row_number一點應用
- 使用rownum分頁排序奇怪現象一則:前後幾次查詢資料不一樣排序
- 【Oracle】-【ROWNUM與索引】-索引對ROWNUM檢索的影響Oracle索引
- sql tuning—分析10與11g在處理rownum及rowid的效能區別—part1SQL
- 不一樣的vue實戰(3): 佈局與元件Vue元件
- 與簡書一樣的網站,簡潔。與簡書不一樣的網站,聚合網站
- JDK的版本不一樣,對xml的解析器也不一樣.JDKXML
- windows與linux ping 顯示的ip不一樣WindowsLinux
- 查詢與插入資料使用rownum與level
- str跟unicode不一樣Unicode
- 【實驗】【SQL】排序與rownum的關係暨利用rownum處理一實際需求SQL排序
- Oracle ROWNUMOracle
- JDK1.8 不一樣的HashMapJDKHashMap
- 不一樣的角度理解Vue元件Vue元件
- 網站快照標題描述為什麼與實際不一樣網站
- python與c語言的語法有哪些不一樣的PythonC語言
- 【ROWID】Oracle rowid說明Oracle
- 不一樣的釋出會不一般的品高雲
- 2019 總結不一樣!
- 不一樣的圖片載入方式
- 不一樣的django2.0筆記Django筆記
- 不一樣的Flink入門教程
- iOS 10 來點不一樣的推送iOS
- ROWID的結構與組成 zt
- oracle的rownumOracle
- rownum 詳解
- oracle rownum分頁與顯示記錄小測Oracle
- Defect和Bug有什麼不一樣? -Nikita
- 人大:和清、北做不一樣的AIAI
- win下面不一樣的git bush體驗Git
- 不一樣的 SQL Server 日期格式化SQLServer
- 不一樣的命令模式(設計模式十五)設計模式