程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> 為什麼有時Oracle 數據庫不用索引來查找數據?

為什麼有時Oracle 數據庫不用索引來查找數據?

編輯:Oracle數據庫基礎

當你運用 SQL 語言,向數據庫發布一條查詢語句時, ORACLE 將伴隨產生一個“執行計劃”,也就是該語句將通過何種數據搜索方案執行,是通過全表掃描、還是通過索引搜尋等其它方式。搜索方案的選用與 Oracle 的優化器息息相關。

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() 函數進行轉換,從而導致第六種現象的發生。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved