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

2021-08-21 23:21:18 字數 3496 閱讀 3507

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 掌握了充分反映實際的統計資料,才有可能做出正確的選擇。

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

第十一,看是否有用到並行查詢( pqo )。並行查詢將不會用到索引。如我們想要用到 a 表的 ind_col1 索引的話,可採用以下方式:

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

注意,注釋符必須跟在 select 之後,且注釋中的「 + 」要緊跟著注釋起始符「 /* 」或「 -- 」,否則 hint 就被認為是一般注釋,對 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資料庫不用索引來查詢資料

為什麼有時oracle資料庫不用索引來查詢資料?sql語句的執行步驟 一條sql語句的處理過程要經過以下幾個步驟。1 語法分析 分析語句的語法是否符合規範,衡量語句中各表示式的意義。2 語義分析 檢查語句中涉及的所有資料庫物件是否存在,且使用者有相應的許可權。3 檢視轉換 將涉及檢視的查詢語句轉換為...

為什麼使用資料庫

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

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

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