oracle数据库优化--基本概念
oracle性能不好,首要檢查數(shù)據(jù)庫(kù)服務(wù)器的硬件配置。包括內(nèi)存參數(shù)調(diào)整,oracle9i以后可以在 企業(yè)管理器 enterprise manager 中 例程--配置--內(nèi)存 中查看內(nèi)存以及pool的大小,通過(guò)建議值來(lái)設(shè)置,該工作應(yīng)該隔段時(shí)間就檢查一次,因?yàn)閜ool的設(shè)置和實(shí)際的數(shù)據(jù)量是相關(guān)的。
一般windows32位服務(wù)器上,分配給oracle的內(nèi)存不必超過(guò)1.7G,因?yàn)閷ぶ纺芰瓦@么大,多余了也是浪費(fèi)。整個(gè)物理內(nèi)存的70%應(yīng)該分配給oracle。
在 例程--配置--內(nèi)存 中,可以看到共享池share pool,它里面存放的是package,procedure,function,常用sql,以及oracle數(shù)據(jù)字典等信息。因?yàn)檫@些信息是常用的,置入此內(nèi)存可以避免經(jīng)常解析和io讀取,以提高性能。高速緩沖區(qū)(SGA)的作用時(shí),將之前查詢的結(jié)果集置入次內(nèi)存,以方面再次查詢時(shí)可以直接從內(nèi)存讀取,減少I(mǎi)O.還有一個(gè)PGA的區(qū),是與用戶連接的session有關(guān)的,以及用來(lái)排序的區(qū)域。在8i以前沒(méi)個(gè)session都回分配一塊內(nèi)存用來(lái)排序,而9i以后,所有用戶session可以共享,這樣避免一個(gè)session的pga不夠而另外用戶的pga浪費(fèi)的情況。
一般來(lái)說(shuō),數(shù)據(jù)庫(kù)調(diào)優(yōu)順序是:磁盤(pán)(讀的次數(shù)越少越好,因此需要改變查詢策略,優(yōu)化查詢sql來(lái)減少讀取次數(shù))、網(wǎng)絡(luò)(數(shù)據(jù)庫(kù)服務(wù)器與應(yīng)用服務(wù)器交互時(shí),如果通過(guò)網(wǎng)絡(luò),則網(wǎng)絡(luò)帶寬可能會(huì)有限制,因?yàn)閹挿稚舷滦?#xff0c;并且還會(huì)傳輸其他網(wǎng)絡(luò)數(shù)據(jù),因此帶寬也是個(gè)要考慮的因素)、內(nèi)存、CPU(后兩者如果太差,性能肯定不好)。
oracle查詢優(yōu)化方式,兩種:RBO,CBO
RBO rule based optimize 基于規(guī)則的優(yōu)化 8i以前采用。因此關(guān)聯(lián)查詢中,要注意表的順序
CBO cost based optimize 基于成本的優(yōu)化 8i(包括)以后采用。與表的順序、where中字段順序無(wú)關(guān)。
關(guān)于索引:
B-TREE索引,結(jié)構(gòu)如下:
root
/ | /
branch1 ........
/|/ ......................
leaf1......
leaf節(jié)點(diǎn)的結(jié)構(gòu)是這樣的:
|索引頭|列長(zhǎng)度|列內(nèi)容|rowid(s)|
一個(gè)葉子節(jié)點(diǎn)的大小大概是8192*8bit,因此一個(gè)字段的長(zhǎng)度即使是50,那么一個(gè)節(jié)點(diǎn)大概能分成100個(gè)子節(jié)點(diǎn),那么100萬(wàn)的記錄,也只需要3級(jí)節(jié)點(diǎn)即可索引完畢,因此一般b-tree的深度不超過(guò)4級(jí),這樣根據(jù)b-tree來(lái)查找一條記錄,最多只需遍歷4個(gè)節(jié)點(diǎn)找到rowid,再根據(jù)rowid查找磁盤(pán)即可得到最終記錄數(shù)據(jù)。
對(duì)某列查詢的結(jié)果集記錄數(shù)如果通常都小于7%,則應(yīng)該在該列添加索引。對(duì)b-tree來(lái)說(shuō),where xx is null條件是不會(huì)利用索引的,因此建議這種列應(yīng)該設(shè)置默認(rèn)值,以避免該列的值存在null的情況,同樣group by 中如果該列有null索引也可能無(wú)效。
bitmap索引:
bitmap索引的結(jié)構(gòu)也是樹(shù)形結(jié)構(gòu),但是葉子節(jié)點(diǎn)的結(jié)構(gòu)與b-tree不一樣。bitmap葉子節(jié)點(diǎn)的結(jié)果大概如下:
<key1 start-rowid end-rowid bitmap>
<key2 start-rowid end-rowid bitmap>
......
其中bitmap的內(nèi)容是110010100011100001這樣的01組合形式,它的長(zhǎng)度與start-rowid和end-rowid之間包含的rowid數(shù)量一致。這樣假設(shè)范圍內(nèi)第9個(gè)rowid對(duì)應(yīng)列的內(nèi)容是key1,那么kei1對(duì)應(yīng)的bitmap中第9個(gè)字符的值就是1,否則就是0。同樣每個(gè)塊的大小是8192*8,那么一個(gè)bitmap索引的葉子節(jié)點(diǎn)大概能索引10000條記錄。
bitmap索引對(duì)null的字段依然有效,具體null的值在bitmap中是取0還是專(zhuān)門(mén)有個(gè)keyX的值是null來(lái)區(qū)分需要再查證。bitmap索引對(duì)or條件的查詢效果非常好,它不適應(yīng)與索引列的值經(jīng)常變化的情況,如果索引列的值經(jīng)常變化,那么對(duì)bitmap索引將是災(zāi)難性的,因?yàn)樗i定所有相關(guān)的葉子節(jié)點(diǎn)所在的塊來(lái)更新bitmap的值,它適用于決策支持系統(tǒng)。
函數(shù)索引:是b-tree索引的一種
函數(shù)索引需要注意的是,實(shí)際sql中用到的函數(shù)掩碼的格式、大小寫(xiě)需要與簡(jiǎn)歷索引中函數(shù)掩碼的格式、大小寫(xiě)一致,否則函數(shù)索引可能無(wú)效。另外trunc(),trim[可以采用ltrim(rtrim(col_xxx))的方式來(lái)避免bug]索引可能會(huì)有不正常的情況,may be bug。建立函數(shù)索引需要當(dāng)前用戶有query rewrite的權(quán)限才能建立。
因?yàn)楹瘮?shù)分為確定性函數(shù)和非確定性函數(shù),因此建立函數(shù)索引只能建立在確定性函數(shù)上。確定性函數(shù)的意思是:針對(duì)同一個(gè)傳入值,該函數(shù)將在任何時(shí)候任何情況下都返回一個(gè)確定的結(jié)果。
reverse索引:反轉(zhuǎn)索引 是函數(shù)索引的一種
它通過(guò)反轉(zhuǎn)記錄的值,來(lái)得到高效的查詢性能。在特殊的一些列中可以采用。
為表添加索引并執(zhí)行analyze分析(后面會(huì)提到分析方式)后,執(zhí)行執(zhí)行某個(gè)sql時(shí),數(shù)據(jù)庫(kù)將根據(jù)分析的結(jié)果來(lái)確定它認(rèn)為最優(yōu)化的方式讀取數(shù)據(jù)庫(kù)得到最終結(jié)果,這種基于成本的優(yōu)化由數(shù)據(jù)庫(kù)自動(dòng)完成。如果要強(qiáng)制某個(gè)sql優(yōu)先采用某個(gè)索引,可以添加hint來(lái)實(shí)現(xiàn),即sql書(shū)寫(xiě)成如下格式:
select /*index(user1.index_xxxx)*/ from table11 where .... 這樣實(shí)際執(zhí)行中會(huì)優(yōu)先采用user1.index_xxxx這個(gè)索引,其中user1表示索引所在的owner,index_xxxx表示索引的名稱(而不是索引列的名稱)
為優(yōu)化查詢,一個(gè)規(guī)則是:盡早過(guò)濾更多的數(shù)據(jù)
通過(guò)plsql developer軟件,view一個(gè)table,在general選項(xiàng)卡中,可以看到 Initial extent/next extent/%increase/max extent等內(nèi)容,這些內(nèi)容界定了該table的擴(kuò)展大小方式等。initail extent表示初始大小,next extent表示當(dāng)前extent不夠用時(shí)下次增加的extent大小,%increase表示增加的比例,max extent表示最多可擴(kuò)展的次數(shù)。其中next extent 和%increase的設(shè)置需要注意,因?yàn)榇硕呤窍嚓P(guān)的,如果擴(kuò)展次數(shù)較多時(shí),可能會(huì)發(fā)現(xiàn)next extent的變得非常大,甚至上G都有可能。
在plsql developer中,新建一個(gè)explain plan window(執(zhí)行計(jì)劃窗口),將實(shí)際要執(zhí)行的sql輸入到窗口中,再按F5或者F8,則將顯示數(shù)據(jù)庫(kù)基于成本的執(zhí)行計(jì)劃。第一列description中,顯示了實(shí)際查詢會(huì)通過(guò)全表掃描還是索引等,一般來(lái)說(shuō)全表掃描必將導(dǎo)致性能下降。其中最后三列值得注意:
cost 表示成本,通過(guò)數(shù)據(jù)庫(kù)io訪問(wèn)和cpu性能計(jì)算得來(lái)
cadinality 根據(jù)遍歷索引或者全表掃描的記錄計(jì)算得來(lái)
bytes 表示訪問(wèn)的數(shù)據(jù)量
一個(gè)優(yōu)化后的sql查詢,以上3個(gè)值應(yīng)該是越小越好。
oracle10g以后,oracle將會(huì)自動(dòng)分析各個(gè)table,以便每次執(zhí)行查詢時(shí)都能獲得最佳速度。之前版本必須手工分析(后面會(huì)提到分析方式)。
高水平線概念:
每個(gè)table有個(gè)高水平線,它將記錄該table最后一次extent的塊的最后一個(gè)點(diǎn)的物理地址,如rowid.實(shí)際執(zhí)行全表掃描時(shí),將掃描table的起點(diǎn)到該高水平線之前所有的數(shù)據(jù)塊。因此即使對(duì)改表執(zhí)行了delete操作,這些delete的記錄會(huì)有一個(gè)標(biāo)記標(biāo)志其已經(jīng)刪除,但是全表掃描依然會(huì)掃描這些即使delete掉的數(shù)據(jù)塊,因此會(huì)影響性能。所以如果要?jiǎng)h除一個(gè)表的全部記錄,應(yīng)該采用truncate關(guān)鍵字,必要的時(shí)候可以重建改表 alter table xxx rebuild;
分析表 analyze :
執(zhí)行分析的語(yǔ)句是
全表分析:analyze table xxx compute statistics;
分析5%的數(shù)據(jù)(速度更快)以及特定列和索引:analyze table xxx estimate statistics sample 5 percent for table for all indexes for all indexed columns;
執(zhí)行analyze后,oracle會(huì)將分析結(jié)果存入數(shù)據(jù)字典中,而數(shù)據(jù)字典會(huì)存在共享池share pool中,因此執(zhí)行sql時(shí)會(huì)馬上查詢?cè)摂?shù)據(jù)字典并得到優(yōu)化的執(zhí)行路徑從而快速得到查詢結(jié)果。
關(guān)于綁定變量:
看下面這段代碼:
declare
v_aa varchar2(2);
v_temp number :=0;
v_aa :='00';
select col_22 into v_temp from table_xx where col_11 =v_aa;---sql1
....
v_aa :='01';
select col_22 into v_temp from table_xx where col_11 =v_aa;---sql2
....
上述代碼中v_aa就是采用了綁定變量的方式,可以看到,以上sql1和sql2一模一樣,oracle在實(shí)際執(zhí)行時(shí),只需要在執(zhí)行sql1時(shí)做詞法、語(yǔ)法、編譯、安全檢查等分析,而執(zhí)行sql2時(shí),它會(huì)發(fā)現(xiàn)該sql已經(jīng)在共享池share pool中存在了,因此就省去了詞法、語(yǔ)法、編譯、安全檢查等分析等分析過(guò)程,從而提高性能。但是很多時(shí)候,我們采用的是如下方式:
select col_22 into v_temp from table_xx where col_11 ='00';---sql1
select col_22 into v_temp from table_xx where col_11 ='01';---sql2
結(jié)果oracle不認(rèn)為這兩個(gè)sql是一致的,因此執(zhí)行sql2之前又會(huì)做詞法、語(yǔ)法、編譯、安全檢查等分析,則性能下降。
在實(shí)際程序開(kāi)發(fā)中,如java中,我們建議采用perparedstatement就是這個(gè)原理。而在oracle過(guò)程函數(shù)中,游標(biāo)是會(huì)默認(rèn)的被認(rèn)為是綁定變量方式的,因此如果采用了游標(biāo),就不必專(zhuān)門(mén)再定義一個(gè)變量來(lái)利用該策略。
但是有時(shí)候綁定變量可能也會(huì)導(dǎo)致性能下降,如某表有10萬(wàn)條記錄,其中性別這一列分男、女兩個(gè)值。如果使用了綁定變量where gender= v_gender 的方式,oracle可能會(huì)采用全表掃描的方式來(lái)查詢(why?),而如果采用了硬編碼where gender='男'的方式,則直接利用了gender列上的索引則會(huì)非常快。
柱狀圖分析
對(duì)某一列進(jìn)行柱狀圖分析,將會(huì)得到該列各種值存在的比例,從而可以避免綁定變量方式可能帶來(lái)的低效.
關(guān)于全索引:
如果某個(gè)查詢的結(jié)果以及where中條件列都在一個(gè)索引里面,則可以利用上全索引方式來(lái)達(dá)到高效。如:
select a,b from t_xxxx where id='zz'非常的慢,而這種sql又會(huì)經(jīng)常頻繁的執(zhí)行,則可以添加一個(gè)索引:id,a,b(條件列id要放在第一位)這種全索引。這樣執(zhí)行上述sql時(shí),只需要檢索索引就能得到結(jié)果,而索引的查詢是非常高效的。在9i之前,這種索引需要注意字段的順序。
物化視圖:meterialized view
要?jiǎng)?chuàng)建物化試圖,必須enable query rewrite
物化試圖的刷新方式有 fast、complete 方式。物化視圖會(huì)將視圖的結(jié)果集存入一個(gè)table中固化,并且可以在table上添加索引,因此能提高性能。實(shí)際運(yùn)用mview時(shí),可以直接查詢mview對(duì)應(yīng)的固化table,也可以查詢與mview創(chuàng)建語(yǔ)句條件一致的原始表,oracle會(huì)自動(dòng)從mview對(duì)應(yīng)的table來(lái)做檢索,而不會(huì)檢索原始表。
視圖的聯(lián)合方式:交叉型、星型
如4個(gè)表的一個(gè)聯(lián)合,則實(shí)際聯(lián)合方式可能是
tab1------tab2
| |
| |
tab3------tab4
也可能是
tab1----tab2----tab3
|
|
tab4
不同的聯(lián)合方式,每次兩兩聯(lián)合過(guò)濾的數(shù)據(jù)不一樣,則速度也可能不一樣。
關(guān)于toad工具中比較有用的幾個(gè)點(diǎn):
如
dba-healthy check,能查詢出數(shù)據(jù)命中率、緩存丟失率等。
最大緩存命中率應(yīng)該>95%的才算好,否則說(shuō)明必須要進(jìn)行調(diào)整了
庫(kù)緩存、字典緩存丟失率應(yīng)該是0才好
分區(qū)數(shù)據(jù)占用率應(yīng)<5%
dba-server statistics
tols-sga-trace等
數(shù)據(jù)分區(qū):
通常一個(gè)表的記錄超過(guò)1千萬(wàn)就應(yīng)該考慮采用分區(qū)的方式。分區(qū)相當(dāng)于將一個(gè)大表分成很多個(gè)小表
分區(qū)方式有:hash(計(jì)算出列的hash值來(lái)根據(jù)hash值分區(qū))
range(范圍分區(qū))-----》list(從range引申出來(lái)的方式)
分區(qū)也是在某個(gè)字段上進(jìn)行的,分區(qū)后再添加索引,必須添加分區(qū)索引而不是全索引
符合分區(qū)時(shí),可以采用先range再hash或者先list再hash的方式,符合分區(qū)不能采用先hash再xx的方式。
將經(jīng)常訪問(wèn)的枚舉、字典、對(duì)照表置入緩沖區(qū)能提高性能
8i以前:alter table xxx cache;
8i后:alter table storage (buffer_pool keap);
緩存有三種方式:
default:默認(rèn)方式,置入緩存中,如果緩存空間不夠,根據(jù)某種算法可能會(huì)被移出緩存
keep:一直放入keep池中,始終不會(huì)清除
recycle:只要空間不夠,就會(huì)清除。因此比default方式的更容易被清除。
總結(jié)
以上是生活随笔為你收集整理的oracle数据库优化--基本概念的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: window mobile 防止系统休眠
- 下一篇: iPhone或让国内运营商划地为牢