Oracle 最佳化器與sql查詢執行順序

bitifi發表於2015-09-22


Oracle在執行一個SQL之前,首先需要看一下SQL的執行計劃,然後在按照執行計劃執行SQL,分析執行計劃的工作是由最佳化器來執行的,在不同的條件下,一個SQL可能存在多條執行計劃,但是在某個特定的時間點,特定的環境下,一定只有一種執行計劃是最優的。

一、最佳化器的型別:

oracle 的最佳化方式有兩種,一種是基於規則的RBO(Rule-Based Optimization),一種是基於開銷或者代價的CBO(Cost-Based Optimization)。

1. RBO: oracle在執行查詢時遵循oracle內部預定義的一些規則。

2. CBO:基於開銷或者代價的執行計劃,這裡的開銷是主要是指CPU和記憶體的使用。最佳化器在判斷是否用這種方式時,主要參照的是表及索引的統計資訊。統計資訊給出表的大小、有少行、每行的長度等資訊。這些統計資訊起初在庫內是沒有的,是你在做analyze後才出現的,很多的時侯過期統計資訊會令最佳化器做出一個錯誤的執行計劃,因些我們應及時更新這些資訊。在Oracle8及以後的版本,Oracle列推薦用CBO的方式。

我們要明瞭,不一定走索引就是優的 ,比如一個表只有兩行資料,一次IO就可以完成全表的檢索,而此時走索引時則需要兩次IO,這時對這個表做全表掃描(full table scan)是最好的。

二、最佳化器的最佳化模式(Optermizer Mode)

最佳化模式包括Rule,Choose,First rows,All rows這四種方式,也就是我們以上所提及的。如下我解釋一下:

Rule:不用多說,即走基於規則的方式。

Choolse:這是我們應觀注的,預設的情況下Oracle用的便是這種方式。指的是當一個表或或索引有統計資訊,則走CBO的方式,如果表或索引沒統計資訊,表又不是特別的小,而且相應的列有索引時,那麼就走索引,走RBO的方式。

First Rows:它與Choose方式是類似的,所不同的是當一個表有統計資訊時,它將是以最快的方式返回查詢的最先的幾行,從總體上減少了響應時間。

All Rows:也就是我們所說的Cost的方式,當一個表有統計資訊時,它將以最快的方式返回表的所有的行,從總體上提高查詢的吞吐量。沒有統計資訊則走基於規則的方式。

備註:檢視執行計劃,在plsql中按F5。如:

SELECT STATEMENT, GOAL = ALL_ROWS   7 4 72

MERGE JOIN CARTESIAN   7 4 72

TABLE ACCESS FULL CSMS Z_STUDENT 3 2 18

BUFFER SORT   4 2 18

TABLE ACCESS FULL CSMS Z_CLASS 2 2 18

三、sql語句的執行順序

1、sql語句的執行步驟:

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

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

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

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

5)選擇最佳化器,不同的最佳化器一般產生不同的“執行計劃”

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

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

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

9)執行“執行計劃”

2、oracle 共享原理:

ORACLE將執行過的SQL語句存放在記憶體的共享池(shared buffer pool)中,可以被所有的資料庫使用者共享 當你執行一個SQL語句(有時被稱為一個遊標)時,如果它和之前的執行過的語句完全相同, ORACLE就能很快獲得已經被解析的語句以及最好的 執行路徑. 這個功能大大地提高了SQL的執行效能並節省了記憶體的使用

三、oracle 語句提高查詢效率的方法:1: where column in(select * from ... where ...); 2:... where exists (select 'X' from ...where ...); 第二種格式要遠比第一種格式的效率高。在Oracle中可以幾乎將所有的IN運算子子查詢改寫為使用EXISTS的子查詢 使用EXIST,Oracle系統會首先檢查主查詢,然後執行子查詢直到它找到第一個匹配項,這就節省了時間 Oracle系統在執行IN子查詢時,首先執行子查詢,並將獲得的結果列表存放在在一個加了索引的臨時表中 避免使用having字句 避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後才對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能透過WHERE子句限制記錄的數目,那就能減少這方面的開銷

3、SQL Select語句完整的執行順序:

1)、from子句組裝來自不同資料來源的資料;

2)、where子句基於指定的條件對記錄行進行篩選;

3)、group by子句將資料劃分為多個分組;

4)、使用聚集函式進行計算;

5)、使用having子句篩選分組;

6)、計算所有的表示式;

7)、使用order by對結果集進行排序。

4、多表連線查詢時順序:

例如:

select * from a inner join b on a.bid=b.id inner join c on b.cid=c.id where a.XXX='XXX'

1).from a、b、c作為資料來源

2).透過where a.XXX='XXX' 篩選a表裡的資料

3).a表與b表依次對比,根據on條件,篩選符合條件的資料集

4).將a、b兩張表得到的結果集再和c中的記錄依次對比,篩選符合條件的資料集

5).完成

注意:

在多表關聯查詢時,哪兩個表先結合查詢,要透過最佳化器的分析,走CBO模式,一般將資料多的放在裡面,資料少的放在外面。這裡是假定排序是a、b、c。




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-1806083/,如需轉載,請註明出處,否則將追究法律責任。

相關文章