通過分析SQL語句的執行計畫優化SQL 四

2021-05-14 09:49:14 字數 2632 閱讀 3989

五: oracle的執行計畫

背景知識:為了更好的進行下面的內容我們必須了解一些概念性的術語:

共享sql語句

為了不重複解析相同的sql語句(因為解析操作比較費資源,會導致效能下降),在第一次解析之後,oracle將sql語句及解析後得到的執行計畫存放在記憶體中。這塊位於系統全域性區域sga(system global area)的共享池(shared buffer pool)中的記憶體可以被所有的資料庫使用者共享。因此,當你執行乙個sql語句(有時被稱為乙個游標)時,如果該語句和之前的執行過的某一語句完全相同,並且之前執行的該語句與其執行計畫仍然在記憶體中存在,則oracle就不需要再進行分析,直接得到該語句的執行路徑。oracle的這個功能大大地提高了sql的執行效能並大大節省了記憶體的使用。使用這個功能的關鍵是將執行過的語句盡可能放到記憶體中,所以這要求有大的共享池(通過設定shared buffer pool引數值)和盡可能的使用繫結變數的方法執行sql語句。

當你向oracle 提交乙個sql語句,oracle會首先在共享記憶體中查詢是否有相同的語句。這裡需要註明的是,oracle對兩者採取的是一種嚴格匹配,要達成共享,sql語句必須完全相同(包括空格,換行等)。

下面是判斷sql語句是否與共享記憶體中某一sql相同的步驟:

1. 對所發出語句的文字串進行hashed。如果hash值與已在共享池中sql語句的hash值相同,則進行第2步:

2.將所發出語句的文字串(包括大小寫、空白和注釋)與在第1步中識別的所有

已存在的sql語句相比較。

例如:

select * from emp where empno = 1000; 

和下列每乙個都不同

select * from emp where empno = 1000;

select * from emp where empno = 1000;

select * from emp where empno = 2000;

在上面的語句中列值都是直接sql語句中的,今後我們將這類sql成為硬編碼sql

或字面值sql

使用繫結變數的sql語句中必須使用相同的名字的繫結變數(bind variables) ,

例如:

a. 該2個sql語句被認為相同

select pin , name from people where pin = :blk1.pin;

select pin , name from people where pin = :blk1.pin;

b. 該2個sql語句被認為不相同

select pin , name from people where pin = :blk1.ot_ind;

select pin , name from people where pin = :blk1.ov_ind;

今後我們將上面的這類語句稱為繫結變數sql。

3. 將所發出語句中涉及的物件與第2步中識別的已存在語句所涉及物件相比較。

例如:

如使用者user1與使用者user2下都有emp表,則

使用者user1發出的語句:select * from emp; 與

使用者user2發出的語句:select * from emp;

被認為是不相同的語句,

因為兩個語句中引用的emp不是指同乙個表。

4. 在sql語句中使用的**變數的**型別必須一致。

如果語句與當前在共享池中的另乙個語句是等同的話,oracle並不對它進行語法分析。而直接執行該語句,提高了執行效率,因為語法分析比較耗費資源。

注意的是,從oracle 8i開始,新引入了乙個cursor_sharing引數,該引數的主要目的就是為了解決在程式設計過程中已大量使用的硬編碼sql問題。因為在實際開發中,很多程式人員為了提高開發速度,而採用類似下面的開發方法:

str_sql string;

int_empno int;

int_empno = 2000;

str_sql = 『select * from emp where empno = 『 + int_empno;

…………

int_empno = 1000;

str_sql = 『select * from emp where empno = 『 + int_empno;

上面的**實際上使用了硬編碼sql,使我們不能使用共享sql的功能,結果是資料庫效率不高。但是從上面的2個語句來看,產生的硬編碼sql只是列值不同,其它部分都是相同的,如果僅僅因為列值不同而導致這2個語句不能共享是很可惜的,為了解決這個問題,引入了cursor_sharing引數,使這類問題也可以使用共享sql,從而使這樣的開發也可以利用共享sql功能。聽起來不錯,oracle真為使用者著想,使使用者在不改變**的情況下還可以利用共享sql的功能。真的如此嗎?天上不會無緣無故的掉乙個餡餅的,oracle對該引數的使用做了說明,建議在經過實際測試後再改該引數的值(預設情況下,該引數的值為exact,語句完全一致才使用共享sql)。因為有可能該變該值後,你的硬編碼sql是可以使用共享sql了,但資料庫的效能反而會下降。 我在實際應用中已經遇到這種情況。所以建議編寫需要穩定執行程式的開發人員最好還是一開始就使用繫結變數的sql。

通過分析SQL語句的執行計畫優化SQL (二)

第1章 效能調整綜述 oracle資料庫是高度可調的資料庫產品。本章描述調整的過程和那些人員應與oracle伺服器的調整有關,以及與調整相關聯的作業系統硬體和軟體。本章包括以下方面 l 誰來調整系統?l 什麼時候調整?l 建立有效調整的目標 l 在設計和開發時的調整 l 調整產品系統 l 監控產品系...

通過分析SQL語句的執行計畫優化SQL 三

四 oracle的優化器 優化器有時也被稱為查詢優化器,這是因為查詢是影響資料庫效能最主要的部分,不要以為只有select語句是查詢。實際上,帶有任何where條件的dml insert update delete 語句中都包含查詢要求,在後面的文章中,當說到查詢時,不一定只是指select語句,也...

通過分析SQL語句的執行計畫優化SQL 五

rowid的概念 rowid是乙個偽列,既然是偽列,那麼這個列就不是使用者定義,而是系統自己給加上的。對每個表都有乙個rowid的偽列,但是表中並不物理儲存rowid列的值。不過你可以像使用其它列那樣使用它,但是不能刪除改列,也不能對該列的值進行修改 插入。一旦一行資料插入資料庫,則rowid在該行...