您好,登錄后才能下訂單哦!
對于優化器而言,它在解析目標SQL,得到執行計劃時至關重要的一點是決定訪問數據的方法,即優化器要決定采用什么樣的方式和方法去訪問目標SQL所需要訪問的存儲在oracle數據庫中的數據。
目標SQL所需要訪問的數據一般存儲在表里,而oracle訪問表中數據的方法有兩種:一種直接訪問表,另一種是先訪問索引,在回表(當然,如果目標sql所要訪問的數據只通過訪問相關的索引就可以得到,那么此時就不需要回表了)
oracle數據庫中直接方位表中數據的方法有兩種:一是全表掃描,而是rowid掃描
1. 全表掃描
全掃描時指oracle在訪問目標表里數據時,會從該表所占用的第一個區(EXTENT)的第一個塊(BLOCK)開始掃描,一直掃描到該表的高水位線(HWM),這段范圍內所有的數據塊oracle都必須讀到。當然oracle會對這期間讀到的所有數據施加目標SQL的where條件中指定的條件,最后只返回那些滿足過濾條件的數據。
不是全表掃描不好,事實上oracle在做全表掃描操作時會使用多塊讀,這在目標表的數據量不大時執行效率是非常高的,但全表掃描最大問題就在于走全表掃描的目標sql的執行時間不穩定,不可控,這個執行時間一定會隨著目標表數據量的遞增而遞增。因為隨著目標表數據量的遞增,它的高水位線會一直不斷上漲,所以全表掃描該表時所需要讀取的數據塊的數量也不斷增加,這意味著全表掃描該表時所需要耗費的I/O資源隨之不斷增加,當然完成對該表的全掃描所需要耗費的時間也會隨之增加。另外,對于CBO而言,所要耗費I/O資源不斷增加意味著全表掃描的成本值也會隨著目標表數據量的遞增而遞增。
在oracle中,如果對目標表不停地插入數據,當分配給該表的現有空間不足時高水位線就會向上移動,但如果你用delete語句從該表中刪除數據,則高水位線并不會隨之往下移動。高水位線的這種特性帶來的負作用是,即使使用delete語句刪除所有數據,高水位線還是再原來的位置,這意味這個全表掃描該表時還是需要掃描該表高水位線下的所有數據塊,所以此時對該表的全表掃描操作所耗費的時間與之前相比不會有明細的改善。
2.ROWID掃描
ROWID掃描是指oracle在訪問目標表里的數據時,直接通過數據所在的rowid去定位并訪問這些數據。rowid表示的是oracle的數據行記錄所在物理存儲地址,也就是說rowid實際上是和oracle中數據塊里的行記錄一一對應的。
既然rowid代表的就是表的數據行所在的物理存儲地址,那么當oracle知道待訪問的數據行所在rowid后,自然就可以根據rowid去直接訪問對應表的相關數據行,這就是rowid的定義。
從嚴格意思來說,oracle中rowid掃描有兩層含義:一種是根據用戶在sql語句中輸入rowid的值直接訪問對應的數據行記錄;另一種是先去訪問相關的索引,然后根據訪問索引后得到的rowid再回表去訪問對應的行記錄。
對oralce中堆表而言,我們可以通過內置的rowid偽劣得到對應行記錄所在的rowid的值(注意,這個rowid只是一個偽劣,在實際的表塊中并不存在該列)然后我們可以通過dbms_rowid包中的相關方法(dbms_rowid.rowid_relative_fno,dbms_rowid.rowid_block_number和dbms_rowid.rowid_row_number)將上述偽列的值翻譯成對應數據行的實際物理存儲地址。
SQL> select empno,ename,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 AAAVREAAEAAAACXAAA 4_151_0
14 rows selected.
從上述顯示內容可以看出,empno為7369的行記錄所對應的rowid偽列的值為“AAAVREAAEAAAACXAAA ”,使用dbms_rowid包對該列翻譯后的值為4_151_0,這表是empno為7369的行記錄實際的物理存儲地址位于4號文件第151個數據塊的第0行記錄(數據塊里數據行記錄的記錄號從0開始算起)
上述rowid偽列的值是可以直接在sql語句中where條件中使用的,這就是oralce中rowid掃描的兩層含義中第一種,根據用戶在sql語句中輸入的rowid的值直接去訪問數據行記錄。
SQL> select empno,ename from emp where rowid='AAAVREAAEAAAACXAAL';
EMPNO ENAME
---------- ----------
7900 JAMES
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。