Oracle優化器的RBO和CBO方式
?
?
1、基于規則的優化方式(Rule-Based Optimization,簡稱為RBO)
?
??? 優化器在分析SQL語句時,所遵循的是Oracle內部預定的一些規則,對數據是不敏感的。它只借助少量的信息來決定一個sql語句的執行計劃,包括:
??? 1) sql語句本身
??? 2) sql中涉及到的table、view、index等的基本信息
??? 3) 本地數據庫中數據字典中的信息(遠程數據庫數據字典信息對RBO是無效的)
?
??? 例如:我們常見的,當一個where子句中的一列有索引時去走索引。但是需要注意,走索引不一定就是優的,比如一個表只有兩行數據,一次IO就可以完成全表的檢索,而此時走索引時則需要兩次IO,這時全表掃描(full table scan)的效率更優。
?
?
2、基于代價的優化方式(Cost-Based Optimization,簡稱為CBO)
?
??? 它是看語句的代價(Cost),通過代價引擎來估計每個執行計劃所需的代價,該代價將每個執行計劃所耗費的資源進行量化,CBO根據這個代價選擇出最優的執行計劃。
?
??? 一個查詢所耗費的資源可分為三部分:I/O代價、CPU代價、NETWORK代價。I/O是指把數據從磁盤讀入內存時所需代價(該代價是查詢所需最主要的,所以在優化時一個基本原則就是降低I/O總次數);CPU代價是指處理內存中數據所需的代價,數據一旦讀入內存,當我們識別出我們所要的數據后,會在這些數據上執行排序(sort)或連接(join)操作,這需要消耗CPU資源;對于訪問遠程節點來說,network代價的花費也是很大的。
?
??? 優化器在判斷是否用這種方式時,主要參照的是表及索引的統計信息。統計信息給出表的大小、有多少行、每行的長度等信息。這些統計信息起初在庫內是沒有的,是做analyze后才出現的,很多的時侯過期統計信息會令優化器做出一個錯誤的執行計劃,因些應及時更新這些信息(dbms_stat.analyze)。
?
??? 如星型連接排列查詢,哈希連接查詢,函數索引,和并行查詢等一些技術都是基于CBD的。
?
?
3、優化模式包括Rule、Choose、First rows、All rows四種方式:
?
???
Rule:基于規則的方式。
?
???
Choolse:默認的情況下Oracle用的便是這種方式。指的是當一個表或或索引有統計信息,則走CBO的方式,如果表或索引沒統計信息,表又不是特別的小,而且相應的列有索引時,那么就走索引,走RBO的方式。
?
???
First Rows:它與Choose方式是類似的,所不同的是當一個表有統計信息時,它將是以最快的方式返回查詢的最先的幾行,從總體上減少了響應時間。
?
???
All Rows:也就是我們所說的Cost的方式,當一個表有統計信息時,它將以最快的方式返回表的所有的行,從總體上提高查詢的吞吐量。沒有統計信息則走RBO的方式。
?
?
4、設定選用哪種優化模式:
?
??? A、在initSID.ora中設定OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS (默認是Choose)
??? B、Sessions級別通過:ALTER SESSION SET OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS
??? C、語句級別用Hint(/*+ ... */)來設定
??? B、Sessions級別通過:ALTER SESSION SET OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS
??? C、語句級別用Hint(/*+ ... */)來設定
?
?
5、一些常見的問題:
?
? A、為什么表的某個字段明明有索引,但執行計劃卻不走索引?
??? 1、優化模式是all_rows的方式
??? 2、表作過analyze,有統計信息
??? 3、表很小,上文提到過的,Oracle的優化器認為不值得走索引。
??? 2、表作過analyze,有統計信息
??? 3、表很小,上文提到過的,Oracle的優化器認為不值得走索引。
?
? B、使用CBO時,SQL語句中為什么不能引用系統數據字典表或視圖?
??? 1、因為系統數據字典表都未被分析過,可能導致極差的“執行計劃”。
??? 2、擅自對數據字典表做分析,可能導致死鎖,或系統性能嚴重下降。
?
? C、使用CBO時如何選擇表連接方式?
??? 1、CBO有時會偏重于SMJ和HJ,但在OLTP系統中,NL一般會更好,因為它高效的使用了索引。
??? 2、SMJ即使相關列上建有索引,最多只能因索引的存在,避免數據排序過程。
??? 3、HJ由于須做HASH運算,索引的存在對數據查詢速度幾乎沒有影響。
?
? D、使用CBO時,需要注意什么嗎?
??? 1、必須保證為表和相關的索引搜集足夠的統計數據,
對數據經常有增、刪、改的表最好定期對表和索引進行分析
??? 2、可用SQL語句:analyze table xxx compute statistics for all indexes
?
? E、為什么有時使用CBO會比較慢?
??? 1、沒有對表或視圖進行Analyze
??? 2、SQL進行CBO時對于沒有Analyze的對象會自動進行Analyze,因此造成運行緩慢
?
?
?
?
更加詳細的信息可見以下轉載:
******************************************************************
?
CBO 和 RBO
gzzg | 10 十一月, 2004 10:16
gzzg | 10 十一月, 2004 10:16
選擇獲取路徑(access path)
1 基于成本(Cost-Based)
優化器會根據這些因素來選擇獲取路徑:
◎語句的可用的獲取路徑
◎估計每個獲取路徑的成本
?
選擇獲取路徑(access path)
1 基于成本(Cost-Based)
優化器會根據這些因素來選擇獲取路徑:
◎語句的可用的獲取路徑
◎估計每個獲取路徑的成本
優化器第一步會根據 where 子句的條件(和對有 sample 或者 sample block 的 from 子句)得到可利用的獲取路徑。然后優化器生成執行計劃,并根據索引、列和表的統計信息估計每個計劃的成本。最后,優化器選擇一個成本最低的執行計劃。
如果有提示(hints)存在的話,那么會覆蓋優化器的路徑選擇,當語句中有 sample 或 sample block 除外。
選擇可利用的獲取路徑,優化器考慮以下的因素:
◎選擇性(Selectivity):就是查詢一個表返回的列的百分比。低百分比查詢的選擇性要比高百分比的好。對于返回查詢結果占表的行數比例比較小的話,使用索引是有效率的,如果比例較大的話,全表掃描會更快一些。為了確定查詢的選擇性,優化器考慮這些信息:
※ where 子句中使用的操作符
※ where 子句中使用的唯一鍵和主鍵
※ 表的統計信息
◎DB_FILE_MULTIBLOCK_READ_COUNT 參數:全表掃描使用多塊讀(multiblock read),所以全表掃描的成本取決于一個多塊讀一次讀取的塊的數量。因此,當 DB_FILE_MULTIBLOCK_READ_COUNT 參數設置的比較大,那么優化器選擇全表掃描的可能性也就比較大。
一個例子:
SELECT *
? FROM emp
? WHERE ename = 'JACKSON';
? 如果 ename 是一個唯一性鍵或是主鍵,優化器很可能就會使用 unique scan on index 來使用索引。
? 如果 ename 不是一個唯一性鍵或是主鍵,那么優化器就會使用下面的統計信息:
? USER_TAB_COLUMNS.NUM_DISTINCT? 表的每一列的數值的數量
? USER_TABLES.NUM_ROWS 表的行數
?
2 基于規則(Rule-Based)
優化器會根據這些因素來選擇獲取路徑:
◎語句的可用的獲取路徑
◎獲取路徑的級別
優化器第一步會根據 where 子句的條件得到可利用的獲取路徑,然后選擇最高級別的獲取路徑。
全表掃描是最低級別的獲取路徑,這就意味著再基于規則的優化器如果有索引可以利用,即使全表掃描更有效率,也不會使用全表掃描。
Where 子句中的條件的順序不影響優化器的選擇。
1 基于成本(Cost-Based)
優化器會根據這些因素來選擇獲取路徑:
◎語句的可用的獲取路徑
◎估計每個獲取路徑的成本
優化器第一步會根據 where 子句的條件(和對有 sample 或者 sample block 的 from 子句)得到可利用的獲取路徑。然后優化器生成執行計劃,并根據索引、列和表的統計信息估計每個計劃的成本。最后,優化器選擇一個成本最低的執行計劃。
如果有提示(hints)存在的話,那么會覆蓋優化器的路徑選擇,當語句中有 sample 或 sample block 除外。
選擇可利用的獲取路徑,優化器考慮以下的因素:
◎選擇性(Selectivity):就是查詢一個表返回的列的百分比。低百分比查詢的選擇性要比高百分比的好。對于返回查詢結果占表的行數比例比較小的話,使用索引是有效率的,如果比例較大的話,全表掃描會更快一些。為了確定查詢的選擇性,優化器考慮這些信息:
※ where 子句中使用的操作符
※ where 子句中使用的唯一鍵和主鍵
※ 表的統計信息
◎DB_FILE_MULTIBLOCK_READ_COUNT 參數:全表掃描使用多塊讀(multiblock read),所以全表掃描的成本取決于一個多塊讀一次讀取的塊的數量。因此,當 DB_FILE_MULTIBLOCK_READ_COUNT 參數設置的比較大,那么優化器選擇全表掃描的可能性也就比較大。
一個例子:
SELECT *
? FROM emp
? WHERE ename = 'JACKSON';
? 如果 ename 是一個唯一性鍵或是主鍵,優化器很可能就會使用 unique scan on index 來使用索引。
? 如果 ename 不是一個唯一性鍵或是主鍵,那么優化器就會使用下面的統計信息:
? USER_TAB_COLUMNS.NUM_DISTINCT? 表的每一列的數值的數量
? USER_TABLES.NUM_ROWS 表的行數
?
2 基于規則(Rule-Based)
優化器會根據這些因素來選擇獲取路徑:
◎語句的可用的獲取路徑
◎獲取路徑的級別
優化器第一步會根據 where 子句的條件得到可利用的獲取路徑,然后選擇最高級別的獲取路徑。
全表掃描是最低級別的獲取路徑,這就意味著再基于規則的優化器如果有索引可以利用,即使全表掃描更有效率,也不會使用全表掃描。
Where 子句中的條件的順序不影響優化器的選擇。
?
獲取路徑的級別(常用):
1???? Single row by rowid??
4???? Single row by unique or primary key??
8???? Composite key??
9???? Single-column indexes??
10?? Bounded range search on indexed columns??
11?? Unbounded range search on indexed columns??
12?? Sort-merge join??
13?? MAX or MIN of indexed column??
14?? ORDER BY on indexed columns??
15?? Full table scan?
1???? Single row by rowid??
4???? Single row by unique or primary key??
8???? Composite key??
9???? Single-column indexes??
10?? Bounded range search on indexed columns??
11?? Unbounded range search on indexed columns??
12?? Sort-merge join??
13?? MAX or MIN of indexed column??
14?? ORDER BY on indexed columns??
15?? Full table scan?
?
Single-column indexes?? :當 Where 子句的等于條件中有一個或者多個單列索引(多個條件必須用 AND 連接)時,查詢會使用 Single-column indexes 。如果 Where 子句中只用到有索引的列,Oracle 會在這個索引上執行一個 range scan 獲得被選擇的行的 rowids ,然后通過這些 rowids 來獲得表中的行。如果 where 子句中有多個 Single-column indexes 的列,Oracle 會在每個索引上執行 range scan ,然后將這些返回的 rowids 的集合進行合并,最后再通過這些合并后的 rowids 的集合來獲取表中的行。Oracle 最多可以合并 5 個索引,如果 where 子句中使用的Single-column indexes 超過 5 個,那么 Oracle 就先合并 5 個得到一個 rowids 的集合,通過這個 rowids 集合來獲取表中的行,再判斷這些行是否符合剩下的條件。
?
Bounded range search on indexed columns?? :在 where 子句中有以下條件時(既有上限也有下限)
column = expr
column >[=] expr AND column <[=] expr
column BETWEEN expr AND expr
column LIKE 'c%'
column = expr
column >[=] expr AND column <[=] expr
column BETWEEN expr AND expr
column LIKE 'c%'
?
Unbounded range search on indexed columns? :在 where 子句中有以下條件時(只有上限或者只有下限)
WHERE column >[=] expr
WHERE column <[=] expr
WHERE column >[=] expr
WHERE column <[=] expr
?
Sort-merge join? :如這樣的語句
SELECT *
??? FROM emp, dept
??? WHERE emp.deptno = dept.deptno;
???
優化模式、計劃的穩定性和提示
◎使用 Cost-based 優化器
為了使用 CBO ,需要收集統計信息和啟用 CBO 。啟用 CBO 有以下集中方法:
確定 OPTIMIZER_MODE? 初始化參數被設置為 CHOOSE ;
可以用有 ALL_ROWS 或者 FIRST_ROWS 選項的? ALTER SESSION SET OPTIMIZER_MODE 語句來使當前的 session 使用 CBO ;
在 sql 語句中使用除了 RULE 的任意提示;
確定 CBO 的目標:是要 best throughput (吞吐量)還是 best reponse time(反應時間) ?
舉一個例子來說,一個聯合語句可以 nested loop 執行,也可以 sort-merge 執行,sort-merge 執行會返回整個查詢結果比較快,而 sort-merge 則返回第一行比較快。所以就看你的目的是什么,是要好的吞吐量還是好的發應時間。
選擇 CBO 的目標取決于應用的需要:
※ 對于應用程序執行批量處理,例如 Oracle Reports ,用戶只關心最終的處理結果,發應時間就不是很重要了;
※ 對于交互式的應用,比如 Oracle Forms 應用或者 SQL*Plus 查詢,反映時間就比較重要了;
※ 對于使用 rownum 的查詢語句,反映時間就是優化的目標了。
Oracle 系統默認吞吐量好 (best throughput)為 CBO 的優化目標,但你可以通過以下的方式改變系統的默認設置:
※ 在 session 級別用 ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS
※ 以 statement 級別用 first_rows 提示
※ 可以在 instance 級別修改初始化參數 OPTIMIZER_MODE
使用柱狀圖來描述不平均分布的數據
對平均分布的數據來說,優化器不需要柱狀圖來估計查詢的成本。但對不平均分布的數據來說,Oracle 允許你創建描述某一特定列的數據分布的柱狀圖,Oracle 將這些柱狀圖存儲在數據字典中提供給 CBO 來使用。柱狀圖是永久存在的對象,所以它們占用空間并需要維護,和所有的優化統計信息一樣,Oracle 用來建立柱狀圖的統計信息都是靜態的。如果一個列的數據分布變化頻繁,那么就需要重新統計。在以下的情況下,列的柱狀圖是無效的:
※ All predicates on the column use bind variables;
※ 列中的數據是均勻分布的;
※ 列沒有在 where 子句中被使用;
※ 列中的數據都是唯一的,并只使用在等于操作中;
創建柱狀圖
要為那些在 where 子句中頻繁使用并且數據分布很不均勻的列創建柱狀圖。包 DBMS_STATS 的存儲過程GATHER_TABLE_STATS 可以用來創建柱狀圖。例如,為 emp 表中的 sal 列創建10柱的柱狀圖:
EXECUTE DBMS_STATS.GATHER_TABLE_STATS
?? ('scott','emp', METHOD_OPT => 'FOR COLUMNS SIZE 10 sal');
統計信息在這些視圖中可以查找到?? USER_TAB_COLUMNS, ALL_TAB_COLUMNS, and DBA_TAB_COLUMNS ,
柱狀圖的信息可以查詢這些視圖:USER_HISTOGRAMS, DBA_HISTOGRAMS, 和 ALL_HISTOGRAMS.
確定柱狀圖的柱的數量(采樣的比率):柱狀圖默認的柱的數量的75,這個值對大多數數據分布來說應該是合適的。當然,柱的數量和數據的分布都影響柱狀圖的可用性,你可以用不同數量的柱進行測試以獲得最優的結果。
SELECT *
??? FROM emp, dept
??? WHERE emp.deptno = dept.deptno;
???
優化模式、計劃的穩定性和提示
◎使用 Cost-based 優化器
為了使用 CBO ,需要收集統計信息和啟用 CBO 。啟用 CBO 有以下集中方法:
確定 OPTIMIZER_MODE? 初始化參數被設置為 CHOOSE ;
可以用有 ALL_ROWS 或者 FIRST_ROWS 選項的? ALTER SESSION SET OPTIMIZER_MODE 語句來使當前的 session 使用 CBO ;
在 sql 語句中使用除了 RULE 的任意提示;
確定 CBO 的目標:是要 best throughput (吞吐量)還是 best reponse time(反應時間) ?
舉一個例子來說,一個聯合語句可以 nested loop 執行,也可以 sort-merge 執行,sort-merge 執行會返回整個查詢結果比較快,而 sort-merge 則返回第一行比較快。所以就看你的目的是什么,是要好的吞吐量還是好的發應時間。
選擇 CBO 的目標取決于應用的需要:
※ 對于應用程序執行批量處理,例如 Oracle Reports ,用戶只關心最終的處理結果,發應時間就不是很重要了;
※ 對于交互式的應用,比如 Oracle Forms 應用或者 SQL*Plus 查詢,反映時間就比較重要了;
※ 對于使用 rownum 的查詢語句,反映時間就是優化的目標了。
Oracle 系統默認吞吐量好 (best throughput)為 CBO 的優化目標,但你可以通過以下的方式改變系統的默認設置:
※ 在 session 級別用 ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS
※ 以 statement 級別用 first_rows 提示
※ 可以在 instance 級別修改初始化參數 OPTIMIZER_MODE
使用柱狀圖來描述不平均分布的數據
對平均分布的數據來說,優化器不需要柱狀圖來估計查詢的成本。但對不平均分布的數據來說,Oracle 允許你創建描述某一特定列的數據分布的柱狀圖,Oracle 將這些柱狀圖存儲在數據字典中提供給 CBO 來使用。柱狀圖是永久存在的對象,所以它們占用空間并需要維護,和所有的優化統計信息一樣,Oracle 用來建立柱狀圖的統計信息都是靜態的。如果一個列的數據分布變化頻繁,那么就需要重新統計。在以下的情況下,列的柱狀圖是無效的:
※ All predicates on the column use bind variables;
※ 列中的數據是均勻分布的;
※ 列沒有在 where 子句中被使用;
※ 列中的數據都是唯一的,并只使用在等于操作中;
創建柱狀圖
要為那些在 where 子句中頻繁使用并且數據分布很不均勻的列創建柱狀圖。包 DBMS_STATS 的存儲過程GATHER_TABLE_STATS 可以用來創建柱狀圖。例如,為 emp 表中的 sal 列創建10柱的柱狀圖:
EXECUTE DBMS_STATS.GATHER_TABLE_STATS
?? ('scott','emp', METHOD_OPT => 'FOR COLUMNS SIZE 10 sal');
統計信息在這些視圖中可以查找到?? USER_TAB_COLUMNS, ALL_TAB_COLUMNS, and DBA_TAB_COLUMNS ,
柱狀圖的信息可以查詢這些視圖:USER_HISTOGRAMS, DBA_HISTOGRAMS, 和 ALL_HISTOGRAMS.
確定柱狀圖的柱的數量(采樣的比率):柱狀圖默認的柱的數量的75,這個值對大多數數據分布來說應該是合適的。當然,柱的數量和數據的分布都影響柱狀圖的可用性,你可以用不同數量的柱進行測試以獲得最優的結果。
?
◎生成統計信息
因為 CBO 依賴從表、簇和索引中得到的統計信息,如果數據的尺寸和分布變化頻繁,那么就要定期地對更新統計信息,以精確地反映數據。Oracle 可以通過以下的技術來產生統計信息:
※ 隨機采樣估計
※ 精確計算
※ 用戶定義的統計方法
由于計算統計信息需要時間和空間,所以經常使用估計而不是計算,除非你想要精確的數據,理由如下:
※ 精確計算總是能提供精確的數值,但需要花費更多的時間。計算一個表的統計信息所需要的時間相當于進行一個全表掃描和排序的所花費的時間。
※ 對于大表來說,大致估計比精確計算要快的多。
為了進行一個精確的計算,Oracle 需要足夠的空間去執行掃描和排序。如果內存中沒有足夠的空間,那么就需要臨時空間。但對索引來說,精確計算不需要占用那么多的空間和時間,所以索引比較適合用來做精確計算。當你為一個表、一個列或者索引生成了統計信息,如果數據字典中已經存在這些對象的統計信息,那么Oracle 會更新這些統計信息,并且使訪問這些對象的分析過的 sql 語句無效。這樣下次這些語句再執行,優化器就會自動地根據新的統計信息選擇一個新的執行計劃。
通過 DBMS_STATS 包來收集統計信息:DBMS_STATS 提供以下的存儲過程來收集統計信息。
GATHER_ INDEX_STATS?? 收集索引的統計信息
GATHER_TABLE_STATS??? 收集表、列和索引的統計信息
GATHER_SCHEMA_STATS?? 收集模式中的所有對象的信息
GATHER_DATABASE_STATS? 收集數據庫中的所有對象的統計信息
收集新的優化器的統計信息:Oracle 建議通過下面的方法來為特定的模式收集新的統計信息。
在收集新的統計信息之前,可以使用 DBMS_STATS.EXPORT_SCHEMA_STATS 去保存原有的統計信息,然后用DBMS_STATS.GATHER_SCHEMA_STATS 來收集新的統計信息。當然,你可以完成用一個存儲過程 GATHER_SCHEMA_STATS 來完成上述兩個功能。
如果發現關鍵的 sql 語句的執行性能有很大程度的降低,可以用更大的樣本來重新統計,或者用 DBMS_STATS.IMPORT_SCHEMA_STATS 來恢復以前的統計信息。
也許你發現新的統計使大部分的 sql 語句提高了性能,有問題的 sql 語句的數量很少,那么可以這樣做:
1. 用舊的統計信息為有問題的 sql 語句創建一個存儲大綱;
2. 使用 DBMS_STATS.IMPORT_SCHEMA_STATS 來恢復新的統計信息;
3. 這樣的應用程序就會使用新的統計信息來執行 sql 語句,另外,你的那些有問題的 sql 語句還可以獲得以前的執行性能。
因為 CBO 依賴從表、簇和索引中得到的統計信息,如果數據的尺寸和分布變化頻繁,那么就要定期地對更新統計信息,以精確地反映數據。Oracle 可以通過以下的技術來產生統計信息:
※ 隨機采樣估計
※ 精確計算
※ 用戶定義的統計方法
由于計算統計信息需要時間和空間,所以經常使用估計而不是計算,除非你想要精確的數據,理由如下:
※ 精確計算總是能提供精確的數值,但需要花費更多的時間。計算一個表的統計信息所需要的時間相當于進行一個全表掃描和排序的所花費的時間。
※ 對于大表來說,大致估計比精確計算要快的多。
為了進行一個精確的計算,Oracle 需要足夠的空間去執行掃描和排序。如果內存中沒有足夠的空間,那么就需要臨時空間。但對索引來說,精確計算不需要占用那么多的空間和時間,所以索引比較適合用來做精確計算。當你為一個表、一個列或者索引生成了統計信息,如果數據字典中已經存在這些對象的統計信息,那么Oracle 會更新這些統計信息,并且使訪問這些對象的分析過的 sql 語句無效。這樣下次這些語句再執行,優化器就會自動地根據新的統計信息選擇一個新的執行計劃。
通過 DBMS_STATS 包來收集統計信息:DBMS_STATS 提供以下的存儲過程來收集統計信息。
GATHER_ INDEX_STATS?? 收集索引的統計信息
GATHER_TABLE_STATS??? 收集表、列和索引的統計信息
GATHER_SCHEMA_STATS?? 收集模式中的所有對象的信息
GATHER_DATABASE_STATS? 收集數據庫中的所有對象的統計信息
收集新的優化器的統計信息:Oracle 建議通過下面的方法來為特定的模式收集新的統計信息。
在收集新的統計信息之前,可以使用 DBMS_STATS.EXPORT_SCHEMA_STATS 去保存原有的統計信息,然后用DBMS_STATS.GATHER_SCHEMA_STATS 來收集新的統計信息。當然,你可以完成用一個存儲過程 GATHER_SCHEMA_STATS 來完成上述兩個功能。
如果發現關鍵的 sql 語句的執行性能有很大程度的降低,可以用更大的樣本來重新統計,或者用 DBMS_STATS.IMPORT_SCHEMA_STATS 來恢復以前的統計信息。
也許你發現新的統計使大部分的 sql 語句提高了性能,有問題的 sql 語句的數量很少,那么可以這樣做:
1. 用舊的統計信息為有問題的 sql 語句創建一個存儲大綱;
2. 使用 DBMS_STATS.IMPORT_SCHEMA_STATS 來恢復新的統計信息;
3. 這樣的應用程序就會使用新的統計信息來執行 sql 語句,另外,你的那些有問題的 sql 語句還可以獲得以前的執行性能。
?
◎統計信息的自動收集
這個特性使你能自動地收集統計信息,你也可以建立有失效統計信息的表的列表或者創建沒有統計信息的表的列表。這就要使用 GATHER_SCHEMA_STATS 和 GATHER_DATABASE_STATS 過程中的 options 和 objlist 參數。
影響 CBO 執行計劃的初始化參數:
OPTIMIZER_FEATURES_ENABLED?
OPTIMIZER_MODE?
OPTIMIZER_PERCENT_PARALLEL?
HASH_AREA_SIZE?
SORT_AREA_SIZE?
DB_FILE_MULTIBLOCK_READ_COUNT?
在數據倉庫中使用下列參數:
ALWAYS_ANTI_JOIN?
HASH_JOIN_ENABLED?
下列參數很少需要改動:
HASH_MULTIBLOCK_IO_COUNT?
OPTIMIZER_SEARCH_LIMIT?
BITMAP_MERGE_AREA_SIZE?
下列參數影響索引的使用:
OPTIMIZER_INDEX_COST_ADJ
OPTIMIZER_INDEX_CACHING
這個特性使你能自動地收集統計信息,你也可以建立有失效統計信息的表的列表或者創建沒有統計信息的表的列表。這就要使用 GATHER_SCHEMA_STATS 和 GATHER_DATABASE_STATS 過程中的 options 和 objlist 參數。
影響 CBO 執行計劃的初始化參數:
OPTIMIZER_FEATURES_ENABLED?
OPTIMIZER_MODE?
OPTIMIZER_PERCENT_PARALLEL?
HASH_AREA_SIZE?
SORT_AREA_SIZE?
DB_FILE_MULTIBLOCK_READ_COUNT?
在數據倉庫中使用下列參數:
ALWAYS_ANTI_JOIN?
HASH_JOIN_ENABLED?
下列參數很少需要改動:
HASH_MULTIBLOCK_IO_COUNT?
OPTIMIZER_SEARCH_LIMIT?
BITMAP_MERGE_AREA_SIZE?
下列參數影響索引的使用:
OPTIMIZER_INDEX_COST_ADJ
OPTIMIZER_INDEX_CACHING
?
CBO 的點滴
※ 大緩存系統的查詢計劃:如果 CBO 的執行計劃是在多用戶,緩存命中率很低的的情況下運行的很好,但在單用戶,緩存命中率高的情況下就不一定運行的好。反過來也一樣。
※ 在分析表之前分析索引:分析表所占用的系統資源要比分析索引多的多,因此,將表的分析和索引的分析分開將是非常有利的。
※? 盡可能產生統計信息:使用提示會激發 CBO 優化器。由于 CBO 優化器是獨立于統計信息的。所以對那些有提示的語句中引用的表進行統計是非常有必要的,即使系統默認的優化器是 RBO .
※ 為用戶自定義的結構提供統計信息的收集,選擇,和成本計算。
※ 大緩存系統的查詢計劃:如果 CBO 的執行計劃是在多用戶,緩存命中率很低的的情況下運行的很好,但在單用戶,緩存命中率高的情況下就不一定運行的好。反過來也一樣。
※ 在分析表之前分析索引:分析表所占用的系統資源要比分析索引多的多,因此,將表的分析和索引的分析分開將是非常有利的。
※? 盡可能產生統計信息:使用提示會激發 CBO 優化器。由于 CBO 優化器是獨立于統計信息的。所以對那些有提示的語句中引用的表進行統計是非常有必要的,即使系統默認的優化器是 RBO .
※ 為用戶自定義的結構提供統計信息的收集,選擇,和成本計算。
?
◎使用 Rule-Based 優化器
Oracle 也支持使用 RBO ,但你在設計新的應用使,應該使用 CBO ,在數據倉庫應用中,尤其如此,因為 CBO 對DSS 系統增加了很多特性。這些增強的特性,比如 hash joins, improved star query processing, and histograms 只在 CBO 中有效。
如果你在 Oracle 6 中開發了 OLTP 應用并對 sql 的執行按照 RBO 進行了優化,那么在將應用升級到更高版本的 Oracle 中時,你可以繼續使用 RBO 。
如果你既沒有收集統計信息,也沒有在你的 sql 語句中使用提示,那么你的語句就會使用 RBO 。當然最終你必須地將你目前的應用移植到 CBO 中,因為,Oracle 服務器會最終不支持 RBO 。
如果你的應用是第三方開發的,那么要和開發商討論決定使用什么優化器最適合你的應用。
你可以通過收集統計信息來 Oracle 使用 CBO 優化器,也可以通過刪除統計信息來轉而使用 RBO 優化器。或者在初始化參數中設置 OPTIMIZER_MODE ,或者用 alter session 命令來確定是使用 CBO 還是使用 RBO 。
Oracle 也支持使用 RBO ,但你在設計新的應用使,應該使用 CBO ,在數據倉庫應用中,尤其如此,因為 CBO 對DSS 系統增加了很多特性。這些增強的特性,比如 hash joins, improved star query processing, and histograms 只在 CBO 中有效。
如果你在 Oracle 6 中開發了 OLTP 應用并對 sql 的執行按照 RBO 進行了優化,那么在將應用升級到更高版本的 Oracle 中時,你可以繼續使用 RBO 。
如果你既沒有收集統計信息,也沒有在你的 sql 語句中使用提示,那么你的語句就會使用 RBO 。當然最終你必須地將你目前的應用移植到 CBO 中,因為,Oracle 服務器會最終不支持 RBO 。
如果你的應用是第三方開發的,那么要和開發商討論決定使用什么優化器最適合你的應用。
你可以通過收集統計信息來 Oracle 使用 CBO 優化器,也可以通過刪除統計信息來轉而使用 RBO 優化器。或者在初始化參數中設置 OPTIMIZER_MODE ,或者用 alter session 命令來確定是使用 CBO 還是使用 RBO 。
?
◎使用計劃的穩定性(Plan Stability)來保護執行計劃
計劃穩定性能夠使你的應用在數據庫環境發生變化而受到影響。數據庫環境的變化包括優化模式的變化,諸如 SORT_AREA_SIZE 和 BITMAP_MERGE_AREA_SIZE 等影響內存結構的參數的變化。當你的應用的性能不能冒風險的時候,計劃穩定性是非常有用的。
計劃穩定性用存儲大綱來保存執行計劃。Oracle 可以為一個或所有的 sql 語句創建存儲大綱。當你使用存儲大綱時,優化器可以從大綱中生成等同的執行計劃。
保存在存儲大綱中的計劃會保持不變,即使你的系統配置或統計信息發生了改變。由于在后來的 Oracle? 版本中優化器發生了改變,存儲大綱也能穩定地生成執行計劃。你可以將大綱分組成類并對類別進行控制,以簡化大綱的管理和配置。
計劃穩定性也可以使得從 RBO 到 CBO 的移植更容易,當你升級你的 Oracle 的版本時。
計劃穩定性使用提示和精確文本匹配
Oracle 用提示來記錄存儲計劃,計劃穩定性也依賴查詢的精確文本匹配,以確定查詢是否有存儲大綱。
相似的 sql 語句可以共享存儲大綱,當然,在 sql 語句和存儲大綱之間時一對一的關系。語句上數值的不同,就會導致使用不同的存儲大綱。為了避免這個問題,用幫定變量來替代具體的數值。
計劃穩定性依賴于性能比較滿意時刻的存儲的執行計劃。在很多環境中,諸如 dates 和 order numbers 之類的數據類型經常會發生變化。在這些情況下,當數據特征發生大的變化時,還持久地使用存儲計劃會降低系統的性能。這就暗示著計劃穩定性和 CBO 有某種程度上時相反的。CBO 總是試圖在基于精確反映數據的狀態的前提下產生執行計劃。因此,你必須權衡控制使用計劃穩定性。
大綱是如何使用提示的?
一個大綱主要由一組提示組成,就相當于優化器為特定的 sql 語句生成的執行計劃。當 Oracle 創建了大綱,計劃穩定性使用那些產生執行計劃的相同數據來檢查優化結果。也就是說,Oracle 使用執行計劃的輸入來產生一個大綱,而不是執行計劃本身。
你不能修改一個大綱。你可以在 sql 語句種嵌入提示,但這對 Oracle 如何使用大綱是沒有影響的,因為 Oracle 會將修改提示的 sql 語句看成是和存儲在大綱種不同的 sql 語句。
將大綱和 sql 語句匹配
當編譯 sql 語句并將他們和大綱匹配時,使用下面兩種方案種的一種。第一種方案就是,如果你通過設置系統或會話的USE_STORED_OUTLINES 參數為 false。這樣 Oracle 就不會試圖將 sql 語句和大綱進行匹配。第二種方案包含以下兩個匹配步驟:
第一,如果你制定 Oracle 必須使用一個特定類的大綱,那么只用那個類種的大綱才能成為匹配的候選;第二,如果 sql 語句的文本和大綱種的文本精確匹配,那么 Oracle 認為這兩個文本時一致的,并使用這個大綱。如果有任何的不同,比如空格不同,回車換行的變化,內嵌的提示的不同,甚至注釋的不同,就不會進行匹配。
Oracle 如何存儲大綱?
Oracle 在 OL$ 表大綱數據,在 OL$HINTS 存儲提示數據。除非你刪除他們,否則 Oracle 會保留這些大綱。Oracle 將執行計劃保留再緩存中,如果沒有足夠的空間保留他們就需要重新創建。
下面幾個初始化參數可以啟用大綱
QUERY_REWRITE_ENABLED
STAR_TRANSFORMATION_ENABLED
OPTIMIZER_FEATURES_ENABLE
計劃穩定性能夠使你的應用在數據庫環境發生變化而受到影響。數據庫環境的變化包括優化模式的變化,諸如 SORT_AREA_SIZE 和 BITMAP_MERGE_AREA_SIZE 等影響內存結構的參數的變化。當你的應用的性能不能冒風險的時候,計劃穩定性是非常有用的。
計劃穩定性用存儲大綱來保存執行計劃。Oracle 可以為一個或所有的 sql 語句創建存儲大綱。當你使用存儲大綱時,優化器可以從大綱中生成等同的執行計劃。
保存在存儲大綱中的計劃會保持不變,即使你的系統配置或統計信息發生了改變。由于在后來的 Oracle? 版本中優化器發生了改變,存儲大綱也能穩定地生成執行計劃。你可以將大綱分組成類并對類別進行控制,以簡化大綱的管理和配置。
計劃穩定性也可以使得從 RBO 到 CBO 的移植更容易,當你升級你的 Oracle 的版本時。
計劃穩定性使用提示和精確文本匹配
Oracle 用提示來記錄存儲計劃,計劃穩定性也依賴查詢的精確文本匹配,以確定查詢是否有存儲大綱。
相似的 sql 語句可以共享存儲大綱,當然,在 sql 語句和存儲大綱之間時一對一的關系。語句上數值的不同,就會導致使用不同的存儲大綱。為了避免這個問題,用幫定變量來替代具體的數值。
計劃穩定性依賴于性能比較滿意時刻的存儲的執行計劃。在很多環境中,諸如 dates 和 order numbers 之類的數據類型經常會發生變化。在這些情況下,當數據特征發生大的變化時,還持久地使用存儲計劃會降低系統的性能。這就暗示著計劃穩定性和 CBO 有某種程度上時相反的。CBO 總是試圖在基于精確反映數據的狀態的前提下產生執行計劃。因此,你必須權衡控制使用計劃穩定性。
大綱是如何使用提示的?
一個大綱主要由一組提示組成,就相當于優化器為特定的 sql 語句生成的執行計劃。當 Oracle 創建了大綱,計劃穩定性使用那些產生執行計劃的相同數據來檢查優化結果。也就是說,Oracle 使用執行計劃的輸入來產生一個大綱,而不是執行計劃本身。
你不能修改一個大綱。你可以在 sql 語句種嵌入提示,但這對 Oracle 如何使用大綱是沒有影響的,因為 Oracle 會將修改提示的 sql 語句看成是和存儲在大綱種不同的 sql 語句。
將大綱和 sql 語句匹配
當編譯 sql 語句并將他們和大綱匹配時,使用下面兩種方案種的一種。第一種方案就是,如果你通過設置系統或會話的USE_STORED_OUTLINES 參數為 false。這樣 Oracle 就不會試圖將 sql 語句和大綱進行匹配。第二種方案包含以下兩個匹配步驟:
第一,如果你制定 Oracle 必須使用一個特定類的大綱,那么只用那個類種的大綱才能成為匹配的候選;第二,如果 sql 語句的文本和大綱種的文本精確匹配,那么 Oracle 認為這兩個文本時一致的,并使用這個大綱。如果有任何的不同,比如空格不同,回車換行的變化,內嵌的提示的不同,甚至注釋的不同,就不會進行匹配。
Oracle 如何存儲大綱?
Oracle 在 OL$ 表大綱數據,在 OL$HINTS 存儲提示數據。除非你刪除他們,否則 Oracle 會保留這些大綱。Oracle 將執行計劃保留再緩存中,如果沒有足夠的空間保留他們就需要重新創建。
下面幾個初始化參數可以啟用大綱
QUERY_REWRITE_ENABLED
STAR_TRANSFORMATION_ENABLED
OPTIMIZER_FEATURES_ENABLE
?
◎創建大綱
Oracle 可以自動地為所有的 sql 語句創建大綱,或者你可以為一個特定的 sql 語句創建大綱。不管是哪一種情況,大綱可以從 RBO 中獲得輸入,也可以從 CBO 中獲得。
當你將參數 CREATE_STORED_OUTLINES 設置為 TRUE,那么 Oracle 就會自動地創建存儲大綱。一旦被激活,Oracle 就會為所有的執行的 sql 語句創建大綱。你也可以使用 CREATE OUTLINE 來為特定的 sql 語句創建存儲大綱。
為存儲大綱創建和指定類別
你可以創建大綱類別,并將一些存儲大綱指定給它。這會給管理一組存儲大綱帶來方便。
參數 CREATE_STORED_OUTLINES 和 CREATE OUTLINE 語句都接受類別的名稱,在這兩種錢情況下,如果你在其中指定一個類別的名稱,Oracle 會將所有后來創建的存儲大綱指定到這個類別中,除非重新設置這個類別的名稱或者將參數CREATE_STORED_OUTLINES 設置為 FALSE。
如果你在參數 CREATE_STORED_OUTLINES 和 CREATE OUTLINE 語句中都沒有指定類別的名稱,Oracle 會將大綱指定為 DEFALT 的類別中。
使用存儲大綱
指定的存儲大綱只對有大綱的 sql 語句的編譯進行控制,如果你將參數 USE_STORED_OUTLINES to FALSE 設置為 FALSE ,Oracle 就不會使用存儲大綱。當你將 USE_STORED_OUTLINES 設置為 FALSE ,而將CREATE_STORED_OUTLINES 設置為 TRUE,Oracle 會創建存儲大綱,但不會使用它們。當你激活存儲大綱時,Oracle 總是使用 CBO ,這是因為大綱依賴于提示。
你可以通過這兩個數據字典 USER_OUTLINES,USER_OUTLINE_HINTS? 來查看查看大綱。
Oracle 可以自動地為所有的 sql 語句創建大綱,或者你可以為一個特定的 sql 語句創建大綱。不管是哪一種情況,大綱可以從 RBO 中獲得輸入,也可以從 CBO 中獲得。
當你將參數 CREATE_STORED_OUTLINES 設置為 TRUE,那么 Oracle 就會自動地創建存儲大綱。一旦被激活,Oracle 就會為所有的執行的 sql 語句創建大綱。你也可以使用 CREATE OUTLINE 來為特定的 sql 語句創建存儲大綱。
為存儲大綱創建和指定類別
你可以創建大綱類別,并將一些存儲大綱指定給它。這會給管理一組存儲大綱帶來方便。
參數 CREATE_STORED_OUTLINES 和 CREATE OUTLINE 語句都接受類別的名稱,在這兩種錢情況下,如果你在其中指定一個類別的名稱,Oracle 會將所有后來創建的存儲大綱指定到這個類別中,除非重新設置這個類別的名稱或者將參數CREATE_STORED_OUTLINES 設置為 FALSE。
如果你在參數 CREATE_STORED_OUTLINES 和 CREATE OUTLINE 語句中都沒有指定類別的名稱,Oracle 會將大綱指定為 DEFALT 的類別中。
使用存儲大綱
指定的存儲大綱只對有大綱的 sql 語句的編譯進行控制,如果你將參數 USE_STORED_OUTLINES to FALSE 設置為 FALSE ,Oracle 就不會使用存儲大綱。當你將 USE_STORED_OUTLINES 設置為 FALSE ,而將CREATE_STORED_OUTLINES 設置為 TRUE,Oracle 會創建存儲大綱,但不會使用它們。當你激活存儲大綱時,Oracle 總是使用 CBO ,這是因為大綱依賴于提示。
你可以通過這兩個數據字典 USER_OUTLINES,USER_OUTLINE_HINTS? 來查看查看大綱。
?
◎用 outln_pkg 包來管理概要
包 outln_pkg 有下面三個存儲過程:drop_unused, drop_by_cat, update_by_cat
移動大綱表:
Oracle 利用 OL$ 和 OL$HINTS 表創建了視圖 USER_OUTLINES 和 USER_OUTLINE_HINTS ,Oracle 在 sys 表空間中使用模式 OUTLN 創建了這些表。如果大綱在 sys 表空間中使用了太多的空間,你可以將它們移到另外的表空間中去。
包 outln_pkg 有下面三個存儲過程:drop_unused, drop_by_cat, update_by_cat
移動大綱表:
Oracle 利用 OL$ 和 OL$HINTS 表創建了視圖 USER_OUTLINES 和 USER_OUTLINE_HINTS ,Oracle 在 sys 表空間中使用模式 OUTLN 創建了這些表。如果大綱在 sys 表空間中使用了太多的空間,你可以將它們移到另外的表空間中去。
?
◎使用提示
作為一個程序設計者,你可能知道一些優化器不知道的信息,例如,你知道某個索引對某中查詢特別有效。基于這種信息,你可以選擇一個比優化器更為有效的執行計劃,這就是提示。你可以勇提示來說明:
※ sql 的優化路徑
※ sql 的基于成本的路徑的目標
※ 從表中獲取數據的路徑
※ 合并語句的合并順序
※ 合并語句中的合并操作
說明提示,你可以在以下三種語句中使用提示:簡單的 select , update, 或 delete 語句中,一個復雜查詢中的父句或者子句部分,復合查詢中的一部分(由 union 連接的 )。
一個語句塊只能有一個包含提示的注釋,注釋只能跟在 select, update, 或者 delete 關鍵詞的后面,有兩種形式:
select? /*+ hint text */
select - - + hint text
加號就會使得 Oracle 將注釋翻譯為一系列的提示,加號必須緊跟在注釋符的后面,不可以存在空格。如果注釋中包含多個提示,那么提示之間必須至少用一個空格分隔開。如果提示表示的不正確,那么 Oracle 會忽略但不返回錯誤。
?
決定優化路徑和目標的提示:ALL_ROWS, FIRST_ROWS, CHOOSE, RULE 如果在 sql 語句中使用了決定優化路徑和目標的提示,那么優化器會忽略統計信息的存在,初始化參數 OPTIMIZER_MODE 的值和 alter session 語句對 OPTIMIZER_MODE 的設置。
決定獲取方法的提示:FULL, ROWID, HASH ...
決定合并操作的提示:USE_NL, USE_MERGE, USE_HASH, ...
決定并行執行的提示:PARALLEL , NOPARALLEL , PQ_DISTRIBUTE , APPEND ...
其他提示:CACHE ,NOCACHE ,MERGE ,NO_MERGE
******************************************************************
決定獲取方法的提示:FULL, ROWID, HASH ...
決定合并操作的提示:USE_NL, USE_MERGE, USE_HASH, ...
決定并行執行的提示:PARALLEL , NOPARALLEL , PQ_DISTRIBUTE , APPEND ...
其他提示:CACHE ,NOCACHE ,MERGE ,NO_MERGE
******************************************************************
?
?