為什麼有時ORACLE資料庫不用索引來查詢資料

2021-06-21 16:31:18 字數 4116 閱讀 7269

為什麼有時oracle資料庫不用索引來查詢資料?

sql語句的執行步驟 

一條sql語句的處理過程要經過以下幾個步驟。 

1 語法分析 分析語句的語法是否符合規範,衡量語句中各表示式的意義。 

2 語義分析 檢查語句中涉及的所有資料庫物件是否存在,且使用者有相應的許可權。 

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

4 表示式轉換 將複雜的sql表示式轉換為較簡單的等效連線表示式。 

5 選擇優化器 不同的優化器一般產生不同的「執行計畫」 

6 選擇連線方式 oracle有三種連線方式,對多表連線oracle可選擇適當的連線方式。 

7 選擇連線順序 對多表連線oracle選擇哪一對表先連線,選擇這兩表中哪個表做為源資料表。 

8 選擇資料的搜尋路徑 根據以上條件選擇合適的資料搜尋路徑,如是選用全表搜尋還是利用索引或是其他的方式。 

9 執行「執行計畫」 

oracle的優化器 

oracle有兩種優化器:基於規則的優化器(rbo, rule based optimizer),和基於代價的優化器(cbo, cost based optimizer)。 

rbo自oracle 6版以來被採用,有著一套嚴格的使用規則,只要你按照它去寫sql語句,無論資料表中的內容怎樣,也不會影響到你的「執行計畫」,也就是說對資料不「敏感」,oracle公司已經不再發展這種技術了。 

cbo自oracle 7版被引入,oracle自7版以來採用的許多新技術都是基於cbo的,如星型連線排列查詢,雜湊連線查詢,和並行查詢等。cbo計算各種可能「執行計畫」的「代價」,即cost,從中選用cost最低的方案,作為實際執行方案。各「執行計畫」的cost的計算根據,依賴於資料表中資料的統計分布,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的共有sort merge join(smj)、hash join(hj)和nested loop join(nl)。在兩張表連線,且內錶的目標列上建有索引時,只有nested loop才能有效地利用到該索引。smj即使相關列上建有索引,最多只能因索引的存在,避免資料排序過程。hj由於須做hash運算,索引的存在對資料查詢速度幾乎沒有影響。 

第四,看連線順序是否允許使用相關索引。假設表emp的deptno列上有索引,表dept的列deptno上無索引,where語句有emp.deptno=dept.deptno條件。在做nl連線時,emp做為外表,先被訪問,由於連線機制原因,外表的資料訪問方式是全表掃瞄,emp.deptno上的索引顯然是用不上,最多在其上做索引全掃瞄或索引快速全掃瞄。 

第五,是否用到系統資料字典表或檢視。由於系統資料字典表都未被分析過,可能導致極差的「執行計畫」。但是不要擅自對資料字典表做分析,否則可能導致死鎖,或系統效能下降。 

第六,索引列是否函式的引數。如是,索引在查詢時用不上。 

第七,是否存在潛在的資料型別轉換。如將字元型資料與數值型資料比較,oracle會自動將字元型用to_number()函式進行轉換,從而導致第六種現象的發生。 

第八,是否為表和相關的索引蒐集足夠的統計資料。對資料經常有增、刪、改的表最好定期對錶和索引進行分析,可用sql語句「analyze table ***x compute statistics for all indexes;"。oracle掌握了充分反映實際的統計資料,才有可能做出正確的選擇。 

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

我們假設典型情況,有表emp,共有一百萬行資料,但其中的emp.deptno列,資料只有4種不同的值,如10、20、30、40。雖然emp資料行有很多,oracle預設認定表中列的值是在所有資料行均勻分布的,也就是說每種deptno值各有25萬資料行與之對應。假設sql搜尋條件deptno=10,利用deptno列上的索引進行資料搜尋效率,往往不比全表掃瞄的高,oracle理所當然對索引「視而不見」,認為該索引的選擇性不高。 

但我們考慮另一種情況,如果一百萬資料行實際不是在4種deptno值間平均分配,其中有99萬行對應著值10,5000行對應值20,3000行對應值30,2000行對應值40。在這種資料分布圖案中對除值為10外的其它deptno值搜尋時,毫無疑問,如果索引能被應用,那麼效率會高出很多。我們可以採用對該索引列進行單獨分析,或用analyze語句對該列建立直方圖,對該列蒐集足夠的統計資料,使oracle在搜尋選擇性較高的值能用上索引。 

第十,索引列值是否可為空(null)。如果索引列值可以是空值,在sql語句中那些需要返回null值的操作,將不會用到索引,如count(*),而是用全表掃瞄。這是因為索引中儲存值不能為全空。 

第十一,看是否有用到並行查詢(pqo)。並行查詢將不會用到索引。 

第十二,看pl/sql語句中是否有用到bind變數。由於資料庫不知道bind變數具體是什麼值,在做非相等連線時,如「<」,「>」,「like」等。oracle將引用預設值,在某些情況下會對執行計畫造成影響。 

如果從以上幾個方面都查不出原因的話,我們只好用採用在語句中加hint的方式強制oracle使用最優的「執行計畫」。 

hint採用注釋的方式,有行注釋和段注釋兩種方式。 

如我們想要用到a表的ind_col1索引的話,可採用以下方式: 

「select /*+ index(a ind_col1)*/ * from a where col1 = ***;" 

注意,注釋符必須跟在select之後,且注釋中的「+」要緊跟著注釋起始符「/*」或「--」,否則hint就被認為是一般注釋,對pl/sql語句的執行不產生任何影響。 

兩種有效的跟蹤除錯方法 

oracle提供了兩種有效的工具來跟蹤除錯pl/sql語句的執行計畫。 

一種是explain table方式。使用者必須首先在自己的模式(schema)下,建立plan_table表,執行計畫的每一步驟都將記錄在該表中,建表sql指令碼為在$/rdbms/admin/下的utlxplan.sql。 

開啟sql*plus,輸入「set autotrace on」,然後執行待除錯的sql語句。在給出查詢結果後,oracle將顯示相應的「執行計畫」,包括優化器型別、執行代價、連線方式、連線順序、資料搜尋路徑以及相應的連續讀、物理讀等資源代價。 

如果我們不能確定需要跟蹤的具體sql語句,比如某個應用使用一段時間後,響應速度忽然變慢。我們這時可以利用oracle提供的另乙個有力工具tkprof,對應用的執行過程全程跟蹤。 

我們要先在系統檢視v$session中,可根據userid或machine,查出相應的sid和serial#。 

以sys或其他有執行dbms_system程式包的使用者連線資料庫,執行「execute dbms_system.set_sql_trace_in_session(sid,serial#,true);」。 

然後執行應用程式,這時在伺服器端,資料庫引數「user_dump_dest」指示的目錄下,會生成ora__***x.trc檔案,其中***x為被跟蹤應用的作業系統程序號。 

應用程式執行完成後,用命令tkprof對該檔案進行分析。命令示例:「tkprof tracefile outputfile explain=userid/password"。在作業系統oracle使用者下,鍵入「tkprof」,會有詳細的命令幫助。分析後的輸出檔案outputfile中,有每一條pl/sql語句的「執行計畫」、cpu占用、物理讀次數、邏輯讀次數、執行時長等重要資訊。根據輸出檔案的資訊,我們可以很快發現應用中哪條pl/sql語句是問題的癥結所在。

為什麼有時 Oracle 資料庫不用索引來查詢資料

sql 語句的執行步驟。1 語法分析 分析語句的語法是否符合規範,衡量語句中各表示式的意義。2 語義分析 檢查語句中涉及的所有資料庫物件是否存在,且使用者有相應的許可權。3 檢視轉換 將涉及檢視的查詢語句轉換為相應的對基表查詢語句。4 表示式轉換 將複雜的 sql 表示式轉換為較簡單的等效連線表示式...

為什麼使用資料庫

儘管檔案系統可以解決不少問題,有些問題是檔案系統所無法 解決的,如果給檔案系統加上這些特性,那麼檔案系統也就成 為了乙個資料庫。1.資料的冗餘與資料不一致 重複資料多,而且對於分布式,有可能出現 資料無法同步的問題。2.資料訪問困難,資料孤立 因為資料儲存沒有採取同樣的格式,使得使 用統一的介面訪問...

什麼叫資料庫,為什麼要安裝資料庫?

有關資料庫有嚴格的定義,本文結合自己的理解,通俗簡短的介紹下資料庫 首先我們想一想,電腦的組成上有一大塊的硬碟是用來幹什麼的?用來存放資料的。這個硬碟就相當於乙個大型倉庫,裡面空空如也,就是乙個大的空著的空間。一般是誰能往裡面放置東西呢?各種軟體。然而每一種軟體存放資料的方式是不一樣的,比如對於同樣...