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