Decode360's Blog

          業(yè)精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評(píng)論 :: 0 Trackbacks
          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è)定
          ?
          ?
          5、一些常見的問題:
          ?
          ? A、為什么表的某個(gè)字段明明有索引,但執(zhí)行計(jì)劃卻不走索引?
          ??? 1、優(yōu)化模式是all_rows的方式
          ??? 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

          選擇獲取路徑(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)化器的選擇。
          ?
          獲取路徑的級(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?
          ?
          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%'
          ?
          Unbounded range search on indexed columns? :在 where 子句中有以下條件時(shí)(只有上限或者只有下限)
          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é)果。
          ?
          ◎生成統(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í)行性能。
          ?
          ◎統(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
          ?
          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ì)算。
          ?
          ◎使用 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 。
          ?
          ◎使用計(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
          ?
          ◎創(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? 來查看查看大綱。
          ?
          ◎用 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 表空間中使用了太多的空間,你可以將它們移到另外的表空間中去。
          ?

          ◎使用提示
          作為一個(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
          ******************************************************************
          ?
          ?
          ?
          posted on 2008-08-13 21:33 decode360 閱讀(1464) 評(píng)論(0)  編輯  收藏 所屬分類: 07.Oracle
          主站蜘蛛池模板: 岗巴县| 额济纳旗| 六盘水市| 蒙山县| 舒兰市| 姜堰市| 莱阳市| 玉龙| 南宁市| 滕州市| 民和| 曲沃县| 吉安市| 蓬安县| 丘北县| 闽侯县| 济源市| 南城县| 濮阳县| 莲花县| 萝北县| 峡江县| 黄骅市| 云林县| 平凉市| 中方县| 镇江市| 凌源市| 嵩明县| 扬州市| 蓝田县| 富裕县| 黄大仙区| 汕尾市| 青铜峡市| 密山市| 临清市| 惠水县| 青海省| 津南区| 竹溪县|