通過ROWID訪問表(table access by ROWID)
ROWID是一個偽列,即是一個非用戶定義的列,而又實際存儲於數據庫之中。每一個表都有一個ROWID列,一個ROWID值用於唯一確定數據庫表中的的一條記錄。因此通過ROWID 方式來訪問數據也是 Oracle 數據庫訪問數據的實現方式之一。一般情況下,ROWID方式的訪問一定以索引訪問或用戶指定ROWID作為先決條件,因為所有的索引訪問方式最終都會轉換為通過ROWID來訪問數據記錄。(注:index full scan 與index fast full scan除外)由於Oracle ROWID能夠直接定位一條記錄,因此使用ROWID方式來訪問數據,極大提高數據的訪問效率
ROWID掃描是指Oracle在訪問目標表里的數據時,直接通過數據所在的ROWID去定位並訪問這些數據。
從嚴格意義上來說,Oracle中的ROWID掃描有兩層含義:一種是根據用戶在SQL語句中輸入的ROWID的值直接去訪問對應的數據行記錄;另外一種是先去訪問相關的索引,然后根據訪問索引后得到的ROWID再回表去訪問對應的數據行記錄。
對Oracle中的堆表而言,我們可以通過Oracle內置的ROWID偽列得到對應行記錄所在的ROWID的值(注意,這個ROWID只是一個偽 列,在實際的表塊中並不存在該列),然后我們還可以通過DBMS_ROWID包中的相關方法(dbms_rowid.rowid_object,dbms_rowid.rowid_relative_fno、dbms_rowid.rowid_block_number和 dbms_rowid.rowid_row_number)將上述ROWID偽列的值翻譯成對應數據行的實際物理存儲地址。
我們來看一個使用ROWID偽列和DBMS_ROWID包的實例。執行如下SQL,查詢表EMP中的所有記錄:
SCOTT@PDBORCL> select empno, ename, rowid, dbms_rowid.rowid_object(rowid)||'_'||dbms_rowid.rowid_relative_fno(rowid) || '_' || dbms_rowid.rowid_block_number(rowid) || '_' || dbms_rowid.rowid_row_number(rowid) location from emp; EMPNO ENAME ROWID LOCATION ---------- ---------- ------------------ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------------ 7369 SMITH AAAWh/AAJAAAACVAAA 92287_9_149_0 7499 ALLEN AAAWh/AAJAAAACVAAB 92287_9_149_1 7521 WARD AAAWh/AAJAAAACVAAC 92287_9_149_2 7566 JONES AAAWh/AAJAAAACVAAD 92287_9_149_3 7654 MARTIN AAAWh/AAJAAAACVAAE 92287_9_149_4 7698 BLAKE AAAWh/AAJAAAACVAAF 92287_9_149_5 7782 CLARK AAAWh/AAJAAAACVAAG 92287_9_149_6 7788 SCOTT AAAWh/AAJAAAACVAAH 92287_9_149_7 7839 KING AAAWh/AAJAAAACVAAI 92287_9_149_8 7844 TURNER AAAWh/AAJAAAACVAAJ 92287_9_149_9 7876 ADAMS AAAWh/AAJAAAACVAAK 92287_9_149_10 7900 JAMES AAAWh/AAJAAAACVAAL 92287_9_149_11 7902 FORD AAAWh/AAJAAAACVAAM 92287_9_149_12 7934 MILLER AAAWh/AAJAAAACVAAN 92287_9_149_13 已選擇 14 行。 SCOTT@PDBORCL>
從上述顯示的內容中我們可以看出,EMPNO為7369的行記錄所對應的ROWID偽列的值為"AAAWh/AAJAAAACVAAA",使用 DBMS_ROWID包對該偽列翻譯后的值為"92287_9_149_0",這表示EMPNO為7369的行記錄,對象編號為92287,實際的物理存儲地址位於9號文件的第149個數據塊的第0行記錄(數據塊里數據行記錄的記錄號從0開始算起)。
select file_name,file_id,relative_fno from dba_data_files where relative_fno=9;
SYS@PDBORCL> select file_name,file_id,relative_fno from dba_data_files where relative_fno=9; FILE_NAME FILE_ID RELATIVE_FNO -----------------------------------------------------------------------------------------------------------------------------------------------C:\APP\ORACLE\ORADATA\ORCL\PDBORCL\SAMPLE_SCHEMA_USERS01.DBF 9 9
上述ROWID偽列的值是可以直接在SQL語句的where條件中使用的,這就是Oracle中ROWID掃描的兩層含義中的第一種:根據用戶在SQL語句中輸入的ROWID的值直接去訪問對應的數據行記錄。
現在執行一次如下使用ROWID偽列的SQL:
SCOTT@PDBORCL> select empno,ename from emp where rowid='AAAWh/AAJAAAACVAAA'; EMPNO ENAME ---------- ---------- 7369 SMITH
從上述顯示的內容中我們可以看出,Oracle確實是通過ROWID偽列(即rowid='AAAWh/AAJAAAACVAAA')直接訪問到了EMPNO為7369的行記錄。
執行計划如下:
查詢計划中說明該查詢是的表訪問方式是”TABLE ACCESS BY USER ROWID“,也就是直接通過USER ROWID來訪問