Oracle效能優化
阿新 • • 發佈:2019-01-04
1. 系統級優化
1) 資料庫引數配置
A. 合理分配SGA及其內部引數(經驗值如下):
a) SGA=phy*(60%-80%)
b) Share pool=SAG*45%
c) DB Cache=SGA*45%
d) Log Buffer: 1~3M
注:Oracle9i在Windows下有bug, 是由Windows下的SGA最大值有2G的限制造成的
B. 注意調整process和open cursor引數,這兩個引數直接影響資料庫的session量
2) 分離表和索引:將表和索引建立在不同的表空間,決不要將不屬於Oracle內部系統的物件存放到SYSTEM表空間。同時,確保資料表空間和索引表空間置於不同的硬碟,減少I/O競爭;
3) 如果是企業版資料庫,大表可以考慮採取分割槽儲存措施,提高系統的效能;
4) 優化Export和Import工作:使用較大的BUFFER(比如10MB , 10,240,000)可以提高EXPORT和IMPORT的速度
5) 定期分析查詢計劃,提高資料庫的效能;
2. 索引相關
6) 要對經常查詢的欄位建立索引,但是由於索引管理的開銷,在增刪改操作頻繁的情況下避免建立不必要的索引;
7) 對於只讀或者接近只讀的場合,如資料倉庫,對於勢值比較小的列可以考慮使用bitmap索引;
8) 如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引.
3. SQL相關
9) Oracle的From子句表的順序:記錄越多的表放在越前面(左);
10) Oracle的where子句表示式的順序:過濾掉最大數目記錄的條件放到where子句的末尾;
11) Select子句中避免使用‘*’,增加了查詢表的列的開銷;
12) 在執行結果等效的情況下,使用Truncate代替Delete;
13) 為了在查詢過程中要儘量使用索引,對於like語句避免使用右匹配或者中間匹配的模糊查詢;
14) 將過濾條件儘可能放到Where子句中,而不是放到Having子句中;
15) 在SQL語句中,要減少對錶的查詢,特別是在含有子查詢的SQL子句中;
16) 使用表的別名可以減少解析的時間並避免引起歧義;
17) 使用exists替代in;
18) 用NOT EXISTS替代NOT IN;
19) 通常情況下,採用表連線的方式比exists更有效率;
20) 當提交一個包含一對多表資訊(比如部門表和僱員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換;
21) 使用>=替代〉,這樣DBMS可直接跳到等於的記錄上,可能會避免向前的掃描工作;
22) 用union替代or,通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將造成全表掃描. 注意, 以上規則只針對多個索引列有效. 如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低.
23) 避免在索引列上使用計算,如where語句中的表示式sal *12 > 2500應該改為 sal 〉 2500/12;
24) 避免在索引列上使用IS NULL和IS NOT NULL工作;
25) 如果必要,使用函式索引,如對Upper(name)建立索引;
26) 避免在索引列上使用Not,這樣將執行全表掃描;
27) 如果可能,用union-all替換union語句:當SQL語句需要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 然後在輸出最終結果前進行排序. 如果用UNION ALL替代UNION, 這樣排序就不是必要了. 效率就會因此得到提高.
28) 避免使用耗費資源的操作:帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎,執行耗費資源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序.
29) 儘量避免不必要的排序;
4. 表設計和其它
A. 建立資料庫表時要儘量避免不必要的冗餘項,但是為了提高以後的查詢效率,可以考慮適當的冗餘,這需要做權衡;
B. 能夠批量查詢的情況,不要使用迴圈語句單次查詢,避免IO開銷;
C. 多使用Commit語句:在一個事務中,避免大批量修改的,這樣可能由於不斷擴充回滾段而影響效能;
D. 在寫完一條SQL語句後,使用適當的工具(如Explain plan)檢查SQL語句的效能;
5. Oracle儲存過程編寫經驗和優化措施
1、開發人員如果用到其他庫的Table或View,務必在當前庫中建立View來實現跨庫操作,最好不要直接使用“databse.dbo.table_name”,因為sp_depends不能顯示出該SP所使用的跨庫table或view,不方便校驗。
2、開發人員在提交SP前,必須已經使用set showplan on分析過查詢計劃,做過自身的查詢優化檢查。
3、高程式執行效率,優化應用程式,在SP編寫過程中應該注意以下幾點:
a) SQL的使用規範:
i. 儘量避免大事務操作,慎用holdlock子句,提高系統併發能力。
ii. 儘量避免反覆訪問同一張或幾張表,尤其是資料量較大的表,可以考慮先根據條件提取資料到臨時表中,然後再做連線。
iii. 儘量避免使用遊標,因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該改寫;如果使用了遊標,就要儘量避免在遊標迴圈中再進行表連線的操作。
iv. 注意where字句寫法,必須考慮語句順序,應該根據索引順序、範圍大小來確定條件子句的前後順序,儘可能的讓欄位順序與索引順序相一致,範圍從大到小。
v. 不要在where子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。
vi. 儘量使用exists代替select count(1)來判斷是否存在記錄,count函式只有在統計表中所有行數時使用,而且count(1)比count(*)更有效率。
vii. 儘量使用“>=”,不要使用“>”。 viii. 注意一些or子句和union子句之間的替換
ix. 注意表之間連線的資料型別,避免不同型別資料之間的連線。
x. 注意儲存過程中引數和資料型別的關係。
xi. 注意insert、update操作的資料量,防止與其他應用衝突。如果資料量超過200個數據頁面(400k),那麼系統將會進行鎖升級,頁級鎖會升級成表級鎖。
b) 索引的使用規範:
i. 索引的建立要與應用結合考慮,建議大的OLTP表不要超過6個索引。
ii. 儘可能的使用索引欄位作為查詢條件,尤其是聚簇索引,必要時可以通過index index_name來強制指定索引
iii. 避免對大表查詢時進行table scan,必要時考慮新建索引。
iv. 在使用索引欄位作為條件時,如果該索引是聯合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
v. 要注意索引的維護,週期性重建索引,重新編譯儲存過程。
c) tempdb的使用規範:
i. 儘量避免使用distinct、order by、group by、having、join、***pute,因為這些語句會加重tempdb的負擔。
ii. 避免頻繁建立和刪除臨時表,減少系統表資源的消耗。
iii. 在新建臨時表時,如果一次性插入資料量很大,那麼可以使用select into代替create table,避免log,提高速度;如果資料量不大,為了緩和系統表的資源,建議先create table,然後insert。
iv. 如果臨時表的資料量較大,需要建立索引,那麼應該將建立臨時表和建立索引的過程放在單獨一個子儲存過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。
v. 如果使用到了臨時表,在儲存過程的最後務必將所有的臨時表顯式刪除,先truncate table,然後drop table,這樣可以避免系統表的較長時間鎖定。
vi. 慎用大的臨時表與其他大表的連線查詢和修改,減低系統表負擔,因為這種操作會在一條語句中多次使用tempdb的系統表。
d) 合理的演算法使用:
1) 資料庫引數配置
A. 合理分配SGA及其內部引數(經驗值如下):
a) SGA=phy*(60%-80%)
b) Share pool=SAG*45%
c) DB Cache=SGA*45%
d) Log Buffer: 1~3M
注:Oracle9i在Windows下有bug, 是由Windows下的SGA最大值有2G的限制造成的
B. 注意調整process和open cursor引數,這兩個引數直接影響資料庫的session量
2) 分離表和索引:將表和索引建立在不同的表空間,決不要將不屬於Oracle內部系統的物件存放到SYSTEM表空間。同時,確保資料表空間和索引表空間置於不同的硬碟,減少I/O競爭;
3) 如果是企業版資料庫,大表可以考慮採取分割槽儲存措施,提高系統的效能;
4) 優化Export和Import工作:使用較大的BUFFER(比如10MB , 10,240,000)可以提高EXPORT和IMPORT的速度
5) 定期分析查詢計劃,提高資料庫的效能;
2. 索引相關
6) 要對經常查詢的欄位建立索引,但是由於索引管理的開銷,在增刪改操作頻繁的情況下避免建立不必要的索引;
7) 對於只讀或者接近只讀的場合,如資料倉庫,對於勢值比較小的列可以考慮使用bitmap索引;
8) 如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引.
3. SQL相關
9) Oracle的From子句表的順序:記錄越多的表放在越前面(左);
10) Oracle的where子句表示式的順序:過濾掉最大數目記錄的條件放到where子句的末尾;
11) Select子句中避免使用‘*’,增加了查詢表的列的開銷;
12) 在執行結果等效的情況下,使用Truncate代替Delete;
13) 為了在查詢過程中要儘量使用索引,對於like語句避免使用右匹配或者中間匹配的模糊查詢;
14) 將過濾條件儘可能放到Where子句中,而不是放到Having子句中;
15) 在SQL語句中,要減少對錶的查詢,特別是在含有子查詢的SQL子句中;
16) 使用表的別名可以減少解析的時間並避免引起歧義;
17) 使用exists替代in;
18) 用NOT EXISTS替代NOT IN;
19) 通常情況下,採用表連線的方式比exists更有效率;
20) 當提交一個包含一對多表資訊(比如部門表和僱員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換;
21) 使用>=替代〉,這樣DBMS可直接跳到等於的記錄上,可能會避免向前的掃描工作;
22) 用union替代or,通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將造成全表掃描. 注意, 以上規則只針對多個索引列有效. 如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低.
23) 避免在索引列上使用計算,如where語句中的表示式sal *12 > 2500應該改為 sal 〉 2500/12;
24) 避免在索引列上使用IS NULL和IS NOT NULL工作;
25) 如果必要,使用函式索引,如對Upper(name)建立索引;
26) 避免在索引列上使用Not,這樣將執行全表掃描;
27) 如果可能,用union-all替換union語句:當SQL語句需要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 然後在輸出最終結果前進行排序. 如果用UNION ALL替代UNION, 這樣排序就不是必要了. 效率就會因此得到提高.
28) 避免使用耗費資源的操作:帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎,執行耗費資源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序.
29) 儘量避免不必要的排序;
4. 表設計和其它
A. 建立資料庫表時要儘量避免不必要的冗餘項,但是為了提高以後的查詢效率,可以考慮適當的冗餘,這需要做權衡;
B. 能夠批量查詢的情況,不要使用迴圈語句單次查詢,避免IO開銷;
C. 多使用Commit語句:在一個事務中,避免大批量修改的,這樣可能由於不斷擴充回滾段而影響效能;
D. 在寫完一條SQL語句後,使用適當的工具(如Explain plan)檢查SQL語句的效能;
5. Oracle儲存過程編寫經驗和優化措施
1、開發人員如果用到其他庫的Table或View,務必在當前庫中建立View來實現跨庫操作,最好不要直接使用“databse.dbo.table_name”,因為sp_depends不能顯示出該SP所使用的跨庫table或view,不方便校驗。
2、開發人員在提交SP前,必須已經使用set showplan on分析過查詢計劃,做過自身的查詢優化檢查。
3、高程式執行效率,優化應用程式,在SP編寫過程中應該注意以下幾點:
a) SQL的使用規範:
i. 儘量避免大事務操作,慎用holdlock子句,提高系統併發能力。
ii. 儘量避免反覆訪問同一張或幾張表,尤其是資料量較大的表,可以考慮先根據條件提取資料到臨時表中,然後再做連線。
iii. 儘量避免使用遊標,因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該改寫;如果使用了遊標,就要儘量避免在遊標迴圈中再進行表連線的操作。
iv. 注意where字句寫法,必須考慮語句順序,應該根據索引順序、範圍大小來確定條件子句的前後順序,儘可能的讓欄位順序與索引順序相一致,範圍從大到小。
v. 不要在where子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。
vi. 儘量使用exists代替select count(1)來判斷是否存在記錄,count函式只有在統計表中所有行數時使用,而且count(1)比count(*)更有效率。
vii. 儘量使用“>=”,不要使用“>”。 viii. 注意一些or子句和union子句之間的替換
ix. 注意表之間連線的資料型別,避免不同型別資料之間的連線。
x. 注意儲存過程中引數和資料型別的關係。
xi. 注意insert、update操作的資料量,防止與其他應用衝突。如果資料量超過200個數據頁面(400k),那麼系統將會進行鎖升級,頁級鎖會升級成表級鎖。
b) 索引的使用規範:
i. 索引的建立要與應用結合考慮,建議大的OLTP表不要超過6個索引。
ii. 儘可能的使用索引欄位作為查詢條件,尤其是聚簇索引,必要時可以通過index index_name來強制指定索引
iii. 避免對大表查詢時進行table scan,必要時考慮新建索引。
iv. 在使用索引欄位作為條件時,如果該索引是聯合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
v. 要注意索引的維護,週期性重建索引,重新編譯儲存過程。
c) tempdb的使用規範:
i. 儘量避免使用distinct、order by、group by、having、join、***pute,因為這些語句會加重tempdb的負擔。
ii. 避免頻繁建立和刪除臨時表,減少系統表資源的消耗。
iii. 在新建臨時表時,如果一次性插入資料量很大,那麼可以使用select into代替create table,避免log,提高速度;如果資料量不大,為了緩和系統表的資源,建議先create table,然後insert。
iv. 如果臨時表的資料量較大,需要建立索引,那麼應該將建立臨時表和建立索引的過程放在單獨一個子儲存過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。
v. 如果使用到了臨時表,在儲存過程的最後務必將所有的臨時表顯式刪除,先truncate table,然後drop table,這樣可以避免系統表的較長時間鎖定。
vi. 慎用大的臨時表與其他大表的連線查詢和修改,減低系統表負擔,因為這種操作會在一條語句中多次使用tempdb的系統表。
d) 合理的演算法使用: