1. 程式人生 > >Oracle優化-Oracle訪問資料的幾種方式

Oracle優化-Oracle訪問資料的幾種方式



ORACLE如何訪問資料1.全表掃描(FullTableScansFTS為實現全表掃描, Oracle讀取表中所有行,並檢查每一行是否滿足語句的WHERE限制條件一個多塊讀操作可以使一次I/O能讀取多塊資料塊(db_block_multiblock_read_count引數設定) 而不是隻讀取一個數據塊, 這極大的減 少了I/O總次數, 提高了系統的吞吐量,所以利用多塊讀的方法可以十分高效地實現全表掃描,而且只有在全表掃描的情況下才能使用多塊讀操作。在這種訪問模式下,每個資料塊只被讀一次。使用FTS的前提條件:在較大的表上不建議使用全表掃描,除非取出資料的比較多,超過總量的5%——10%,或你想使用並行查詢功能時。

ExampleSQL>explainplanforselect*fromdual;QueryPlan-----------------------------------------SELECTSTATEMENT[CHOOSE]Cost=TABLEACCESSFULLDUAL全表掃描模式下會讀資料到表的高水位線( HWM即表示表曾經擴充套件的最後一個數據塊),讀取速度依賴於Oracle初始化引數db_block_multiblock_read_count(FTS掃描會使表使用上升到高水位(HWM),HWM標識了表最後寫入資料的塊,如果你DELETE刪除了所有的資料表仍然處於高水位

(HWM),只有用 TRUNCATE才能使表迴歸,FTS使用多IO從磁碟讀取資料塊).

QueryPlan------------------------------------SELECTSTATEMENT[CHOOSE]Cost=1**INDEXUNIQUESCANEMP_I1 --如果索引裡就找到了所要的資料,就不會再去訪問表通過設定db_block_multiblock_read_count可以設定一次IO能讀取的資料塊個數, 從而有效減少全表掃描時的IO總次數, 也就是通過預讀機制將將要訪問的資料塊預先讀入記憶體中。只有在全表掃描情況下才能使用多塊讀操作。

2.通過ROWID的表存取(

TableAccessbyROWIDrowidlookup行的ROWID指出了該行所在的資料檔案、資料塊以及行在該塊中的位置,所以通過ROWID來存取資料可以快速定位到目標資料上,是 Oracle存取單行資料的最快方法。這種存取方法不會用到多塊讀操作, 一次I/O只能讀取一個數據塊。 我們會經常在執行計劃中看到該存取方法,如通過索引查詢資料。使用ROWID存取的方法:

SQL>explainplanforselect*fromdeptwhererowid=''AAAAyGAADAAAAATAAF''QueryPlan------------------------------------SELECTSTATEMENT[CHOOSE]Cost=1TABLEACCESSBYROWIDDEPT[ANALYZED]

3. 索引掃描(IndexScanindexlookup

我們先通過index查詢到資料對應的rowid 對於非唯一索引可能返回多個rowid值),然後根據rowid直接從表中得到具體的資料,這種查詢方式稱為索引掃描或索引查詢 indexlookup)。 一個 rowid唯一的表示一行資料, 該行對應的資料塊是通過一次 I/0得到的, 在此情況下該次 i/o只會讀取一個數據庫塊。在索引中,除了儲存每個索引的值外,索引還儲存具有此值的行對應的 ROWID值。索引掃描可以由 2步組成:1 掃描索引得到對應的 rowid值。2 通過找到的 rowid從表中讀出具體的資料。每步都是單獨的一次 I/O 但是對於索引, 由於經常使用, 絕大多數都已經 CACHE到記憶體中, 所以第 1步的 I/O經常是邏輯 I/O 即資料可以從記憶體中得到。 但是對於第 2步來說, 如果表比較大, 則其資料不可能全在記憶體中, 所以其 I/O很有可能是物理 I/O 是一個機械操作, 相對邏輯

I/O

是極其費時間的。

以如果多大表進行索引掃描, 取出的資料如果大於總量的 5% —— 10%

,使用索引

  1. 掃描會效率下降很多。如下列所示:SQL> explain plan for select empno ename from emp where empno=10Query Plan------------------------------------SELECT STATEMENT [CHOOSE] Cost=1TABLE ACCESS BY ROWID EMP [ANALYZED]INDEX UNIQUE SCAN EMP_I1但是如果查詢的資料能全在索引中找到,就可以避免進行第 2步操作,避免了不必要 I/O,此時即使通過索引掃描取出的資料比較多,效率還是很高的SQL> explain plan for select empno from emp where empno=10;-- 只查詢 empnoQuery Plan------------------------------------SELECT STATEMENT [CHOOSE] Cost=1INDEX UNIQUE SCAN EMP_I1進一步講, 如果 sql語句中對索引列進行排序, 因為索引已經預先排序好了, 所以在執行計劃中不需要再對索引列進行排序SQL> explain plan for select empno, ename from emp where empno > 7876order by empno;Query Plan--------------------------------------------------------------------------------SELECT STATEMENT[CHOOSE] Cost=1TABLE ACCESS BY ROWID EMP [ANALYZED]INDEX RANGE SCAN EMP_I1 [ANALYZED]從這個例子中可以看到: 因為索引是已經排序了的, 所以將按照索引的順序查詢出符合條件的行,因此避免了進一步排序操作。根據索引的型別與 where限制條件的不同, 4種類型的索引掃描:

    1) 索引唯一掃描(index unique scan通過唯一索引查詢一個數值經常返回單個ROWID.如果存在 UNIQUE PRIMARYKEY 約束(它保證了語句只存取單行)的話, Oracle經常實現唯一性掃描。使用唯一性約束的例子:SQL> explain plan for select empno enamefrom empwhere empno=10Query Plan------------------------------------SELECTSTATEMENT[CHOOSE] Cost=1TABLEACCESS BYROWID EMP [ANALYZED]INDEX UNIQUE SCAN EMP_I12) 索引範圍掃描(index range scan使用一個索引存取多行資料,在唯一索引上使用索引範圍掃描的典型情況下是在謂詞 where限制條件)中使用了範圍操作符(如> < <> >= <= between使用索引範圍掃描的例子:SQL> explain plan for select empno ename from emp where empno > 7876orderby empnoQuery Plan--------------------------------------------------------------------------------SELECTSTATEMENT[CHOOSE] Cost=1TABLEACCESS BYROWID EMP [ANALYZED]INDEX RANGE SCAN EMP_I1 [ANALYZED]在非唯一索引上,謂詞col = 5可能返回多行資料,所以在非唯一索引上都使用索引範圍掃描。使用index rang scan3種情況:1 在唯一索引列上使用了range操作符( > < <> >= <= between2 在組合索引上,只使用部分列進行查詢,導致查詢出多行3 對非唯一索引列上進行的任何查詢。3) 索引全掃描(index full scan與全表掃描對應, 也有相應的全索引掃描。而且此時查詢出的資料都必須從索引中可以直接得到。全索引掃描的例子:SQL>explain planforselectempno enamefrombig_emporderbyempnoenameQuery Plan--------------------------------------------------------------------------------SELECTSTATEMENT[CHOOSE] Cost=26INDEX FULLSCAN BE_IX [ANALYZED]4) 索引快速掃描(index fastfull scan掃描索引中的所有的資料塊,在這種存取方法中, 可以使用多塊讀功能,也可以使用並行讀入,以便獲得最大吞吐量與縮短執行時間。

    index full scan很類似,但是一個顯著的區別就是它不對查詢出的資料進行排序, 即資料不是以排序順序被返回。

    索引快速掃描的例子: BE_IX索引是一個多列索引: big_emp empno enameSQL> explain plan for select empno ename from big_empQuery Plan------------------------------------------SELECT STATEMENT[CHOOSE] Cost=1INDEX FAST FULLSCAN BE_IX [ANALYZED]只選擇多列索引的第2列:SQL> explain plan for select ename from big_empQuery Plan------------------------------------------SELECT STATEMENT[CHOOSE] Cost=1INDEX FAST FULLSCAN BE_IX [ANALYZED]