當前位置:成語大全網 - 書法字典 - Oracle數據庫為什麽不使用索引來查找數據?

Oracle數據庫為什麽不使用索引來查找數據?

當妳使用SQL語言向數據庫發布查詢語句時,ORACLE會產生壹個“執行計劃”,即使用什麽數據搜索方案來執行語句,是通過全表掃描還是索引搜索。搜索方案的選擇與ORACLE optimizer密切相關。

SQL語句的執行步驟

SQL語句的處理經歷以下步驟。

1語法分析分析語句的語法是否符合規範,衡量語句中每個表達式的含義。

語義分析檢查語句涉及的所有數據庫對象是否存在,用戶是否有相應的權限。

3視圖轉換將涉及視圖的查詢語句轉換為基表上相應的查詢語句。

4表達式轉換將復雜的SQL表達式轉換為更簡單的等效連接表達式。

5選擇優化器不同的優化器通常會產生不同的“執行計劃”

6選擇連接方式ORACLE有三種連接方式,多表連接ORACLE可以選擇合適的連接方式。

7選擇連接多個表的連接順序。ORACLE選擇先連接哪對表,並將兩個表中的哪壹個用作源數據表。

8選擇數據的搜索路徑根據以上條件選擇合適的數據搜索路徑,如全表搜索、索引或其他方法。

9運行“執行計劃”

ORACLE優化器

ORACLE有兩種優化器:RBO(基於規則的優化器)和CBO(基於成本的優化器)。

RBO從ORACLE版本6開始被采用,它有壹套嚴格的使用規則。只要妳按照它寫SQL語句,無論數據表裏是什麽,都不會影響妳的“執行計劃”,也就是說,對數據不“敏感”。甲骨文公司已經停止開發這項技術。

CBO是從Oracle版本7開始引入的,ORACLE從版本7開始采用的許多新技術都是基於CBO的,比如星型連接排列查詢、哈希連接查詢和並行查詢。CBO計算各種可能的“執行方案”的“成本”,即費用,選擇費用最低的方案作為實際操作方案。每個“執行計劃”的成本的計算基礎取決於數據表中數據的統計分布,這是ORACLE數據庫本身並不清楚的。有必要對該表和相關指標進行分析,以收集CBO所需的數據。

總的來說,CBO選擇的“執行方案”並不比RBO差,而且相對來說,CBO對程序員的要求也沒有RBO那麽苛刻,省去了程序員從多個可能的“執行方案”中選擇壹個最優方案的調試時間,但有些情況會出現問題。

典型的問題有:有時候,明明有索引,查詢過程中卻明顯沒有使用相關索引,導致查詢過程漫長,占用資源巨大。有什麽問題?按照下面的順序,基本可以找到原因。

查找原因的步驟

首先我們需要確定數據庫運行在哪個優化模式下,對應的參數是:optimizer_mode。可以在svrmgrl中運行“show parameter optimizer_mode”來查看。從ORACLE V7開始,默認設置應該是“choose”,即查詢被分析表時選擇CBO,否則選擇RBO。如果該參數設置為“rule”,則無論表是否經過分析,都將選擇RBO,除非在語句中使用hint來強制執行它。

其次,檢查PL/SQL語句的WHERE子句中是否出現了索引列或復合索引的第壹列,這是“執行計劃”在相關索引中使用的必要條件。

第三,看采用什麽類型的連接。ORACLE的* * *包括排序合並連接(SMJ)、散列連接(HJ)和嵌套循環連接(NL)。當兩個表相連接並且內部表的目標列上有索引時,只有嵌套循環可以有效地使用索引。即使相關列上有索引,SMJ最多也只能因為索引的存在而避開數據排序過程。因為HJ要做哈希運算,索引的存在對數據查詢的速度影響不大。

第四,看連接順序是否允許使用相關索引。假設表emp的deptno列上有索引,表dept的deptno列上沒有索引,WHERE語句有EMP的條件。Deptno = Dept.Deptno .進行NL連接時,emp作為外觀首先被訪問。由於連接機制,外觀的數據訪問方式是全表掃描,顯然不需要emp.deptno上的索引。最多可以對其進行全索引掃描或快速全索引掃描。

第五,是否使用系統數據字典表或視圖。因為沒有對系統數據字典表進行分析,可能會導致“執行計劃”非常差。但不要擅自分析數據字典表,否則可能導致死鎖或系統性能下降。

第六,索引列是否是函數的參數。如果是這樣,則查詢中不使用該索引。

第七,是否存在潛在的數據類型轉換。如果將字符型數據與數值型數據進行比較,ORACLE會自動用to_number()函數對字符型數據進行轉換,從而導致第六種現象的發生。

第八,是否為表和相關索引收集了足夠的統計數據。對於數據經常被添加、刪除和更改的表,最好定期對表進行分析和索引。SQL語句“分析表xxxx中所有索引的計算機統計信息;”。甲骨文只有掌握了充分反映現實的統計數據,才能做出正確的選擇。

第九,索引列的選擇性不高。

我們假設壹個典型的情況,有壹個表emp,* *有壹百萬行數據,但是emp.deptno列只有四個不同的值,比如10,20,30,40。雖然有許多emp數據行,但ORACLE默認表中列出的值均勻分布在所有數據行中,這意味著每個deptno值都有250,000個數據行與之對應。假設SQL搜索條件DEPTNO=10,使用DEPTNO列上的索引進行數據搜索的效率往往不會高於全表掃描。甲骨文自然對指數“視而不見”,認為指數沒有選擇性。

但是讓我們考慮另壹種情況。如果壹百萬行數據實際上不是均勻分布在deptno的四個值中,其中,990,000行對應於值10,5,000行對應於值20,300行對應於值30,200行對應於值40。在這種數據分布模式下,毫無疑問,如果可以應用索引,那麽在搜索除10以外的其他deptno值時,效率會高很多。我們可以單獨分析索引列,或者用analyze語句為該列構建直方圖,為該列收集足夠的統計數據,這樣ORACLE在搜索選擇性高的值時就可以使用索引。

第十,索引列值是否可以為空。如果索引列值可以為null,那些需要在SQL語句中返回NULL值的操作將不會使用索引,比如COUNT(*),而是掃描整個表。這是因為存儲在索引中的值不能完全為空。

第十壹,看是否使用了並行查詢(PQO)。並行查詢不會使用索引。

第十二,看PL/SQL語句中是否使用了綁定變量。因為數據庫不知道bind變量的具體值,所以在進行不等連接時,比如“

如果不能從以上幾個方面找出原因,那就只好通過在語句中添加hint來迫使ORACLE使用最優的“執行計劃”了。

提示采用註釋的方式,包括行註釋和段註釋。

如果我們想使用表A的IND_COL1索引,我們可以使用以下方法:

" SELECT/*+INDEX(A IND _ col 1)*/* FROM A WHERE col 1 = XXX;"

註意,註釋字符必須跟在SELECT後面,註釋中的“+”應該緊跟在註釋起始符“/*”或“-”後面,否則hint會被認為是壹般的註釋,對PL/SQL語句的執行沒有影響。

兩種有效的跟蹤和調試方法

ORACLE提供了兩個有效的工具來跟蹤和調試PL/SQL語句的執行計劃。

壹種是解釋表模式。用戶首先要在自己的SCHEMA中創建壹個PLAN_TABLE表,執行計劃的每壹步都會記錄在表中。創建該表的SQL腳本是${ORACLE_HOME}/rdbms/admin/下的utlxplan.sql。

打開SQL*PLUS,輸入“SET AUTOTRACE ON”,然後運行要調試的SQL語句。查詢結果給出後,ORACLE會顯示相應的“執行計劃”,包括優化器類型、執行成本、連接模式、連接順序、數據搜索路徑以及相應的資源成本如連續讀取、物理讀取等。

如果我們不能確定需要跟蹤的具體SQL語句,比如壹個應用使用壹段時間後,響應速度突然變慢。這時,我們可以使用ORACLE提供的另壹個強大的工具TKPROF來跟蹤應用程序的整個執行過程。

我們應該先根據USERID或者MACHINE在system view V$SESSION中找出對應的SID和SERIAL#。

將數據庫與SYS或其他執行過DBMS_SYSTEM包的用戶連接,執行“執行DBMS _ system。Set _ SQL _ trace _ in _ session (SID,SERIAL#,true)”。。

然後運行應用程序。此時在服務器端,在數據庫參數“USER_DUMP_DEST”指示的目錄下,會生成ora__xxxx.trc文件,其中xxxx是被跟蹤應用的操作系統進程號。

執行應用程序後,使用命令tkprof分析文件。命令示例:“tkprof跟蹤文件輸出文件explain = userid/password”。在操作系統ORACLE用戶下,輸入“tkprof”,會有詳細的命令幫助。分析後的outputfile包含每個PL/SQL語句的“執行計劃”、CPU使用率、物理讀取次數、邏輯讀取次數、執行持續時間等重要信息。根據輸出文件中的信息,我們可以快速找出應用程序中哪個PL/SQL語句是問題的癥結所在。