版權聲明:本文發布於http://www.cnblogs.com/yumiko/,版權由Yumiko_sunny所有,歡迎轉載。轉載時,請在文章明顯位置注明原文鏈接。若在未經作者同意的情況下,將本文內容用於商業用途,將保留追究其法律責任的權利。如果有問題,請以郵箱方式聯系作者(793113046@qq.com)。
Oracle訪問數據的方法
Oracle訪問數據主要通過三種辦法實現:
- 通過全表掃描的方式訪問數據
- 通過ROWID訪問數據
- 通過索引的方式訪問數據
1.1 通過全表掃描訪問表(TABLE ACCESS FULL)
- oracle順序讀取表中所有的行,並逐條匹配WHERE限定條件。
- 采用多塊讀的方式進行全表掃描,可以有效提高系統的吞吐量,降低I/O次數。
- 即使創建索引,oracle也會根據CBO的計算結果,決定是否使用索引。
注意事項:
- 只有全表掃描時才可以使用多塊讀。該方式下,單個數據塊僅訪問一次。
- 對於數據量較大的表,不建議使用全表掃描進行訪問。
- 當訪問表中的數據量超過數據總量的5%—10%時,通常oracle會采用全表掃描的方式進行訪問。
- 並行查詢可能會導致優化器選擇全表掃描的方式。
示例:
Yumiko@sunny >set autotrace traceonly
Yumiko@sunny >select * from scott.emp; 已選擇14行。 執行計划 ---------------------------------------------------------- Plan hash value: 3956160932 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| EMP | 14 | 518 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 統計信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 1539 bytes sent via SQL*Net to client 492 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 14 rows processed
其中,紅色的“TABLE ACCESS FULL”表示采用的全表掃描。
1.2 通過ROWID訪問表(TABLE ACCESS BY ROWID)
- ROWID是數據存放在數據庫中的物理地址,能夠唯一標識表中的一條數據。
- ROWID指出了一條記錄所在的數據文件、塊號以及行號的位置,因此通過ROWID定位單行數據是最快的方法。
注意事項:
- ROWID作為一個偽列,其數值並不存儲在數據庫中,當查詢時才進行計算。
- ROWID除了在同一集簇中可能不唯一外,每條記錄的ROWID唯一。
示例:
--查詢記錄的rowid
Yumiko@sunny >select rowid,ename from scott.emp where ename='SMITH'; ROWID ENAME ------------------ ---------- AAAVREAAEAAAACXAAA SMITH --利用rowid查詢數據 Yumiko@sunny >set autotrace on Yumiko@sunny >select empno,ename from scott.emp where rowid='AAAVREAAEAAAACXAAA'; EMPNO ENAME ---------- ---------- 7369 SMITH 執行計划 ---------------------------------------------------------- Plan hash value: 1116584662 ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 22 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY USER ROWID| EMP | 1 | 22 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------- 統計信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 1 consistent gets 0 physical reads 0 redo size 598 bytes sent via SQL*Net to client 520 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
其中,紅色的“TABLE ACCESS BY USER ROWID”表示采用ROWID方式訪問數據。
1.3 通過INDEX訪問表
- 通過索引查找相應數據行的rowid,再根據rowid查找表中實際數據的方式稱為“索引查找”或者“索引掃描”。
- 一個rowid對應一條數據行(根據rowid查找結果,僅需要對rowid相應數據的數據塊進行一次I/O操作),因此該方式屬於“單塊讀”。
- 對於索引,除了存儲索引的數據外,還保存有該數據對應的rowid信息。
- 索引掃描分為兩步:1)掃描索引確定相應的rowid信息。 2)根據rowid從表中獲得對應的數據。
注意事項:
- 對於選擇性高的數據行,索引的使用會提升查詢的性能。但對於DML操作,尤其是批量數據的操作,可能會導致性能的降低。
- 全表掃描的效率不一定比索引掃描差,關鍵看數據在數據塊上的具體分布。
示例:
--查看目標用戶的索引對象及其名稱
Yumiko@sunny >select owner,object_name,object_type from dba_objects where owner='SCOTT'; OWNER OBJECT_NAME OBJECT_TYPE ------------------------------ -------------------- ------------------- SCOTT PK_DEPT INDEX SCOTT DEPT TABLE SCOTT EMP TABLE SCOTT PK_EMP INDEX SCOTT BONUS TABLE SCOTT SALGRADE TABLE
--查看目標索引所在的表及其列信息 Yumiko@sunny >select index_name,table_name,column_name from dba_ind_columns where index_name='PK_EMP'; INDEX_NAME TABLE_NAME COLUMN_NAME ------------------------------ ------------------------------ -------------------- PK_EMP EMP EMPNO
--打開會話跟蹤 Yumiko@sunny >set autotrace on
--使用索引列執行查詢並查看執行計划
Yumiko@sunny >select empno,ename from scott.emp where empno='7369'; EMPNO ENAME ---------- ---------- 7369 SMITH 執行計划 ---------------------------------------------------------- Plan hash value: 2949544139 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 10 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 10 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO"=7369) 統計信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 2 consistent gets 1 physical reads 0 redo size 598 bytes sent via SQL*Net to client 520 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
上面紅色的“INDEX UNIQUE SCAN”表示采用了索引掃描。同時根據執行計划,可以清晰地看到索引掃描的執行路徑,既先進行索引掃描,然后根據得到的rowid信息進行表數據的訪問。