ORACLE SQL效能優化一

2021-10-07 03:07:55 字數 3939 閱讀 1405

1. 選用適合的oracle優化器

2. 訪問table的方式

3. 共享sql語句

4. 選擇最有效率的表名順序(只在基於規則的優化器中有效)

5. where子句中的連線順序.

6. select子句中避免使用 『 * 『

7. 減少訪問資料庫的次數

1. 選用適合的oracle優化器 

oracle的優化器共有3種:

設定預設的優化器,可以通過對init.ora檔案中optimizer_mode引數的各種宣告,如rule,cost,choose,all_rows,first_rows . 你當然也在sql句級或是會話(session)級對其進行覆蓋.

為了使用基於成本的優化器(cbo, cost-based optimizer) , 你必須經常執行analyze 命令,以增加資料庫中的物件統計資訊(object statistics)的準確性.

如果資料庫的優化器模式設定為選擇性(choose),那麼實際的優化器模式將和是否執行過analyze命令有關. 如果table已經被analyze過, 優化器模式將自動成為cbo , 反之,資料庫將採用rule形式的優化器.

在預設情況下,oracle採用choose優化器, 為了避免那些不必要的全表掃瞄(full table scan) , 你必須盡量避免使用choose優化器,而直接採用基於規則或者基於成本的優化器.

2. 訪問table的方式

oracle 採用兩種訪問表中記錄的方式:

3. 共享sql語句

為了不重複解析相同的sql語句,在第一次解析之後, oracle將sql語句存放在記憶體中.這塊位於系統全域性區域sga(system global area)的共享池(shared buffer pool)中的記憶體可以被所有的資料庫使用者共享. 因此,當你執行乙個sql語句(有時被稱為乙個游標)時,如果它和之前的執行過的語句完全相同, oracle就能很快獲得已經被解析的語句以及最好的執行路徑. oracle的這個功能大大地提高了sql的執行效能並節省了記憶體的使用.

可惜的是oracle只對簡單的表提供高速緩衝(cache buffering) ,這個功能並不適用於多表連線查詢. 資料庫管理員必須在init.ora中為這個區域設定合適的引數,當這個記憶體區域越大,就可以保留更多的語句,當然被共享的可能性也就越大了. 當你向oracle 提交乙個sql語句,oracle會首先在這塊記憶體中查詢相同的語句.

這裡需要註明的是,oracle對兩者採取的是一種嚴格匹配,要達成共享,sql語句必須完全相同(包括空格,換行等).

共享的語句必須滿足三個條件:

4. 選擇最有效率的表名順序(只在基於規則的優化器中有效)

oracle的解析器按照從右到左的順序處理from子句中的表名,因此from子句中寫在最後的表(基礎表 driving table)將被最先處理. 在from子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表.當oracle處理多個表時, 會運用排序及合併的方式連線它們.首先,掃瞄第乙個表(from子句中最後的那個表)並對記錄進行排序,然後掃瞄第二個表(from子句中最後第二個表),最後將所有從第二個表中檢索出的記錄與第乙個表中合適記錄進行合併.

例如:

表 tab1 16,384 條記錄

表 tab2 1 條記錄

選擇tab2作為基礎表 (最好的方法)

select count(*) from tab1,tab2 執行時間0.96秒

選擇tab2作為基礎表 (不佳的方法)

select count(*) from tab2,tab1 執行時間26.09秒

如果有3個以上的表連線查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表.

例如:

emp表描述了location表和category表的交集.

select * 

from location   l ,

category  c, 

emp  e

where e.emp_no between 1000 and 2000

and e.cat_no = c.cat_no

and e.locn = l.locn

將比下列sql更有效率

select *

from emp e ,

location l ,

category c

where e.cat_no = c.cat_no

and e.locn = l.locn

and e.emp_no between 1000 and 2000

5. where子句中的連線順序.

oracle採用自下而上的順序解析where子句,根據這個原理,表之間的連線必須寫在其他where條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在where子句的末尾.

例如:

(低效,執行時間156.3秒)

select …

from emp e

where sal > 50000

and job = 『manager'

and 25 < (select count(*) from emp

where mgr=e.empno);

(高效,執行時間10.6秒)

select …

from emp e

where 25 < (select count(*) from emp

where mgr=e.empno)

and sal > 50000

and job = 『manager';

6. select子句中避免使用 『 * 『

當你想在select子句中列出所有的column時,使用動態sql列引用 『*' 是乙個方便的方法.不幸的是,這是乙個非常低效的方法. 實際上,oracle在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味著將耗費更多的時間.

7. 減少訪問資料庫的次數

當執行每條sql語句時, oracle在內部執行了許多任務作: 解析sql語句, 估算索引的利用率, 繫結變數 , 讀資料塊等等. 由此可見, 減少訪問資料庫的次數 , 就能實際上減少oracle的工作量.

例如,

以下有三種方法可以檢索出雇員號等於0342或0291的職員.

方法1 (最低效)

select emp_name , salary , grade

from emp

where emp_no = 342;

select emp_name , salary , grade

from emp

where emp_no = 291;

方法2 (次低效)

declare

cursor c1 (e_no number) is

select emp_name,salary,grade

from emp

where emp_no = e_no;

begin

open c1(342);

fetch c1 into …,..,.. ;

…..

open c1(291);

fetch c1 into …,..,.. ;

close c1;

end;

方法3 (高效)

select a.emp_name , a.salary , a.grade,

b.emp_name , b.salary , b.grade

from emp a,emp b

where a.emp_no = 342

and b.emp_no = 291;

注意:

在sql*plus , sql*forms和pro*c中重新設定arraysize引數, 可以增加每次資料庫訪問的檢索資料量 ,建議值為200

ORACLE SQL效能優化系列 一

1.選用適合的oracle優化器 oracle的優化器共有3種 a.rule 基於規則 b.cost 基於成本 c.choose 選擇性 設定預設的優化器,可以通過對init.ora檔案中optimizer mode引數的各種宣告,如rule,cost,choose,all rows,first r...

ORACLE SQL效能優化系列(一)

1.選用適合的oracle優化器 oracle的優化器共有3種 a.rule 基於規則 b.cost 基於成本 c.choose 選擇性 設定預設的優化器,可以通過對init.ora檔案中optimizer mode引數的各種宣告,如rule,cost,choose,all rows,first r...

ORACLE SQL效能優化系列 一

關鍵字 oracel sql performance tuning 出處 http dbasupport.1.選用適合的oracle優化器 oracle的優化器共有3種 a.rule 基於規則 b.cost 基於成本 c.choose 選擇性 設定預設的優化器,可以通過對init.ora檔案中opt...