Oracle 10g SQL 優化再學習

2021-08-30 04:56:05 字數 4147 閱讀 4985

從8i到10g,oracle不斷進化自己的sql tuning智慧型,一些秘籍級的優化口訣已經失效。

但我喜歡失效,不用記口訣,操個toad for oracle xpert ,按照大方向舒舒服服的調優才是愛做的事情。

1.excution plan

excution plan是最基本的調優概念,不管你的調優吹得如何天花亂墮,結果還是要由excution plan來顯示oracle 最終用什麼索引、按什麼順序連線各表,full table scan還是access by rowid index,瓶頸在什麼地方。如果沒有它的指導,一切調優都是蒙的。

2.toad for oracle xpert

用它來調優在真的好舒服。quest 吞併了lecco後,將它整合到了toad 的sql tunning裡面:最清晰的執行計畫顯示,自動生成n條等價sql、給出優化建議,不同sql執行計畫的對比,還有實際執行的邏輯讀、物理讀資料等等一目了然。

3.索引

大部分的效能問題其實都是索引應用的問題,where子句、order by、group by 都要用到索引。

一般開發人員認為將索引建全了就可以下班回家了,實則還有頗多的思量和陷阱。

3.1 索引列上不要進行計算

這是最最普遍的失效陷阱,比如where trunc(order_date)=trunc(sysdate), i+2>4。索引失效的原因也簡單,索引是針對原值建的二叉樹,你將列值*3/4+2折騰一番後,原來的二叉樹當然就用不上了。解決的方法:

1. 換成等價語法,比如trunc(order_date) 換成

where order_date

>

trunc(sysdate)-1

andorder_date

<

trunc(sysdate)+1

2.    特別為計算建立函式索引

create

index

i_***x 

onshop_order(trunc(order_date))

3.    將計算從等號左邊移到右邊

這是針對某些無心之失的糾正,把a*2>4 改為a>4/2;把to_char(zip) = '94002' 改為zip = to_number('94002');

3.2 cbo與索引選擇性

建了索引也不一定會被oracle用的,就像個挑食的孩子。基於成本的優化器(cbo, cost-based optimizer),會先看看表的大小,還有索引的重複度,再決定用還是不用。表中有100 條記錄而其中有80 個不重複的索引鍵值. 這個索引的選擇性就是80/100 = 0.8,留意toad裡顯示索引的selective和cardinailty。實在不聽話時,就要用hints來調教。

另外,where語句存在多條索引可用時,只會選擇其中一條。所以索引也不是越多越好:)

3.3 索引重建

傳說中資料更新頻繁導致有20%的碎片時,oracle就會放棄這個索引。寧可信其有之下,應該時常alter index rebuild一下。

3.4 其他要注意的地方

不要使用not,如goods_no != 2,要改為

where

goods_no

>2or

goods_no

<2

不要使用is null , 如where dept_code is not null 要改為

where

dept_code 

>=0;

3.5 select 的列如果全是索引列時

又如果沒有where 條件,或者where條件全部是索引列時,oracle 將直接從索引裡獲取資料而不去讀真實的資料表,這樣子理論上會快很多,比如

select

order_no,order_time 

from

shop_order 

where

shop_no=4

當order_no,order_time,shop_no 這三列全為索引列時,你將看到乙個和平時完全不同的執行計畫。

3.6 位圖索引

傳說中當資料值較少,比如某些表示分類、狀態的列,應該建位圖索引而不是普通的二叉樹索引,否則效率低下。不過看執行計畫,這些位圖索引鮮有被oracle臨幸的。

4.減少查詢往返和查詢的表

這也是很簡單的大道理,程式與oracle互動的成本極高,所以乙個查詢能完成的不要分開兩次查,如果乙個迴圈執行1萬條查詢的,怎麼都快不到**去了。

4.1 封裝pl/sql儲存過程

最高端的做法是把迴圈的操作封裝到pl/sql寫的儲存過程裡,因為儲存過程都在服務端執行,所以沒有資料往返的消耗。

4.2 封裝pl/sql內部函式

有機會,將一些查詢封裝到函式裡,而在普通sql裡使用這些函式,同樣是很有效的優化。

4.3 decode/case

但儲存過程也麻煩,所以有case/decode把幾條條件基本相同的重複查詢合併為一條的用法:

select

count

(case

when

price 

<

13then

1else

null

end) low,

count

(case

when

price 

between

13and

15then

1else

null

end) med,

count

(case

when

price 

>

15then

1else

null

end) high

from

products;

4.4 一種where/update語法

select

tab_name 

from

tables

where

(tab_name,db_ver) 

=(( 

select

tab_name,db_ver)

from

tab_columns 

where

version 

=604)

update

empset

(emp_cat, sal_range)=(

select

max(category)

from

emp_categories)

5.其他優化

5.1rowid和rownum

連hibernate 新版也支援rowid了,證明它非常有用。比如號稱刪除重複資料的最快寫法:

delete

from

emp e

where

e.rowid 

>

(select

min(x.rowid)

from

emp x

where

x.emp_no 

=e.emp_no);

6.終極秘技 -hints

這是oracle dba的玩具,也是終極**,比如oracle在cbo,rbo中所做的選擇總不合自己心水時,可以用它來強力調教一下oracle,結果經常讓人喜出望外。

如果開發人員沒那麼多時間來專門學習它,可以依靠toad sql opmitzer 來自動生成這些提示,然後對比一下各種提示的實際效果。不過隨著10g智慧型的進化,hints的驚喜少了。

7. 找出要優化的top sql

磨了這麼久的槍,如果找不到敵人是件鬱悶的事情。

幸虧10g這方面做得非常好。進入web管理介面,就能看到當前或者任意一天的sql列表,按效能排序。

有了它,sql trace和tkprof都可以不用了。

Oracle 10g SQL 優化再學習

2005年11月15日 10 59 00 從8i到10g,oracle不斷進化自己的sql tuning智慧型,一些秘籍級的優化口訣已經失效。但我喜歡失效,不用記口訣,操個toad for oracle xpert 按照大方向舒舒服服的調優才是愛做的事情。1.excution plan excuti...

Oracle 10g SQL 優化再學習

從8i到10g,oracle不斷進化自己的sql tuning智慧型,一些秘籍級的優化口訣已經失效。但我喜歡失效,不用記口訣,操個toad for oracle xpert 按照大方向舒舒服服的調優才是愛做的事情。1.excution plan excution plan是最基本的調優概念,不管你的...

Oracle 10g SQL 優化再學習

從8i到10g,oracle不斷進化自己的sql tuning智慧型,一些秘籍級的優化口訣已經失效。但我喜歡失效,不用記口訣,操個toad for oracle xpert,按照大方向舒舒服服的調優才是愛做的事情。1.excution plan excution plan是最基本的調優概念,不管你的...