Oracle數(shù)據(jù)庫(kù)SQL性能優(yōu)化

1. 選用適合的oracle優(yōu)化器

了解一下,oracle優(yōu)化器的種類(lèi):3種

  • a. RULE (基于規(guī)則)
  • b. COST (基于成本)
  • c. CHOOSE (選擇性)
2. 訪問(wèn)table的方式

oracle采用兩種方式訪問(wèn)表中的記錄:

  • a. 全表掃描
    全表掃描就是順序地訪問(wèn)表中每條記錄. ORACLE采用一次讀入多個(gè)數(shù)據(jù)塊(database block)的方式優(yōu)化全表掃描.

  • b. 通過(guò)ROWID訪問(wèn)表
    ROWID包含了表中記錄的物理位置信息.ORACLE采用索引(INDEX)實(shí)現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置(ROWID)之間的聯(lián)系.通常索引提供了快速訪問(wèn)ROWID的方法,因此那些基于索引列的查詢(xún)就可以得到性能上的提高.

3. 共享SQL語(yǔ)句

為了不重復(fù)解析相同的SQL語(yǔ)句,在第一次解析之后, ORACLE將SQL語(yǔ)句存放在內(nèi)存中.這塊位于系統(tǒng)全局區(qū)域SGA(system globalarea)的共享池(shared bufferpool)中的內(nèi)存可以被所有的數(shù)據(jù)庫(kù)用戶(hù)共享.因此,當(dāng)你執(zhí)行一個(gè)SQL語(yǔ)句(有時(shí)被稱(chēng)為一個(gè)游標(biāo))時(shí),如果它和之前的執(zhí)行過(guò)的語(yǔ)句完全相同,ORACLE就能很快獲得已經(jīng)被解析的語(yǔ)句以及最好的執(zhí)行路徑. ORACLE的這個(gè)功能大大地提高了SQL的執(zhí)行性能并節(jié)省了內(nèi)存的使用.

4. 選擇最優(yōu)效率的表名順序(只在基于規(guī)則的優(yōu)化器中有效)

Oracle的解析器按照從右到左的順序處理from字句中的表名,因此FROM子句中寫(xiě)在最后的表(基礎(chǔ)表 driving table)將被最先處理.在FROM子句中包含多個(gè)表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表.

如果有3個(gè)以上的表連接查詢(xún),那就需要選擇交叉表(intersectiontable)作為基礎(chǔ)表,交叉表是指那個(gè)被其他表所引用的表.

雖然這種只在基于規(guī)則的優(yōu)化器中有效,但這樣寫(xiě)絕對(duì)不會(huì)錯(cuò),因?yàn)榛谄渌?guī)則的會(huì)首先檢索出基礎(chǔ)表然后進(jìn)行首先處理.

5. WHERE字句中的連接順序 (強(qiáng)烈推薦!!!)

ORACLE采用自下而上的順序解析WHERE子句,根據(jù)這個(gè)原理,表之間的連接必須寫(xiě)在其他WHERE條件之前,那些可以過(guò)濾掉最大數(shù)量記錄的條件必須寫(xiě)在WHERE子句的末尾.

6. SELECT子句中避免使用 ‘ * ‘ (強(qiáng)烈推薦!!!)
7. 使用DECODE函數(shù)來(lái)減少處理時(shí)間

使用DECODE函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表.

8. 在刪除全表時(shí),用TRUNCATE替代DELETE (強(qiáng)烈推薦!!!)

這樣使用時(shí),而且無(wú)需執(zhí)行COMMIT操作.

9. 選擇合適的時(shí)機(jī)使用COMMIT (強(qiáng)烈推薦!!!)

比如,我在實(shí)現(xiàn)某個(gè)業(yè)務(wù)需求,在需要頻繁操作數(shù)據(jù)庫(kù)的地方,設(shè)置每操作500次COMMIT一次.

10. 計(jì)算記錄條數(shù) (強(qiáng)烈推薦!!!)

和一般的觀點(diǎn)相反,count(*)比count(1)稍快,當(dāng)然如果可以通過(guò)索引檢索,對(duì)索引列的計(jì)數(shù)仍舊是最快的.例如COUNT(ID).

這個(gè)我之前一直錯(cuò)誤的以為count(1)是最快的.

11. 用WHERE子句替換HAVING子句 (強(qiáng)烈推薦!!!)

避免使用HAVING子句, HAVING 只會(huì)在檢索出所有記錄之后才對(duì)結(jié)果集進(jìn)行過(guò)濾.這個(gè)處理需要排序,總計(jì)等操作.如果能通過(guò)WHERE子句限制記錄的數(shù)目,那就能減少這方面的開(kāi)銷(xiāo).

HAVING中的條件一般用于對(duì)一些集合函數(shù)的比較,如COUNT()等等.除此而外,一般的條件應(yīng)該寫(xiě)在WHERE子句中.

12. 使用表的別名,減少解析的時(shí)間 (強(qiáng)烈推薦!!!)
13. 用EXISTS替代IN,用NOT EXISTS替代NOT IN. (強(qiáng)烈推薦!!!)
14. 通過(guò)腳本來(lái)識(shí)別低效執(zhí)行的SQL語(yǔ)句.

這種方式,其實(shí)我還不是太熟悉.先記錄下.

15. 用EXPLAIN PLAN分析SQL語(yǔ)句. (強(qiáng)烈推薦!!!)
16. 合理的使用索引來(lái)提高效率 (強(qiáng)烈推薦!!!)

雖然使用索引能得到查詢(xún)效率的提高,但是我們也必須注意到它的代價(jià).索引需要空間來(lái)存儲(chǔ),也需要定期維護(hù),每當(dāng)有記錄在表中增減或索引列被修改時(shí),索引本身也會(huì)被修改.這意味著每條記錄的INSERT,DELETE,UPDATE將為此多付出4,5次的磁盤(pán)I/O.因?yàn)樗饕枰~外的存儲(chǔ)空間和處理,那些不必要的索引反而會(huì)使查詢(xún)反應(yīng)時(shí)間變慢.

定期重構(gòu)索引是有必要的.

17. 用UNION替換OR(適用于索引列) (強(qiáng)烈推薦!!!)

通常情況下,用UNION替換WHERE子句中的OR將會(huì)起到較好的效果.對(duì)索引列使用OR將造成全表掃描.注意,以上規(guī)則只針對(duì)多個(gè)索引列有效.如果有column沒(méi)有被索引,查詢(xún)效率可能會(huì)因?yàn)槟銢](méi)有選擇OR而降低.

如果你堅(jiān)持要用OR,那就需要返回記錄最少的索引列寫(xiě)在最前面.

注意: 
WHERE KEY1 = 10  (返回最少記錄) OR KEY2 = 20 (返回最多記錄)
ORACLE內(nèi)部將以上轉(zhuǎn)換為:
WHERE KEY1 = 10 AND ((NOT KEY1 = 10) AND KEY2 = 20)

這個(gè)我在生產(chǎn)環(huán)境中,有應(yīng)用到,實(shí)際效果確實(shí)蠻不錯(cuò)的.

18. 用IN替換OR.
19. 總是使用索引的第一個(gè)列 (強(qiáng)烈推薦!!!)

如果索引是建立在多個(gè)列上,只有在它的第一個(gè)列(leading column)被where子句引用時(shí),優(yōu)化器才會(huì)選擇使用該索引.

20. 用UNION ALL替換UNION (如果有可能的話) (強(qiáng)烈推薦!!!)

當(dāng)SQL語(yǔ)句需要UNION兩個(gè)查詢(xún)結(jié)果集合時(shí),這兩個(gè)結(jié)果集合會(huì)以UNION-ALL的方式被合并,然后在輸出最終結(jié)果前進(jìn)行排序.如果用UNION ALL替代UNION,這樣排序就不是必要了,效率就會(huì)因此得到提高.需要注意的是墓陈,UNION ALL將重復(fù)輸出兩個(gè)結(jié)果集合中相同記錄.因此各位還是要從業(yè)務(wù)需求分析使用UNION ALL的可行性.

21. 需要當(dāng)心的WHERE字句 (強(qiáng)烈推薦!!!!!)
(1) 索引對(duì)不等號(hào)和NOT的限制
    如果WHERE條件中出現(xiàn)!=或者<>,即使該列建立了索引第献,則該索引也不會(huì)被使用贡必;如果不恰當(dāng)?shù)氖褂昧薔OT,則索引也不會(huì)被使用庸毫。
    在下面的例子里, ‘!=’將不使用索引.記住,索引只能告訴你什么存在于表中,而不能告訴你什么不存在于表中.
    不使用索引: SELECT ACCOUNT_NAME FROM TRANSACTION WHERE AMOUNT !=0;
    使用索引: SELECT ACCOUNT_NAME FROM TRANSACTION WHERE AMOUNT >0;
    
    如果索引列是數(shù)字仔拟,則對(duì)于不等號(hào)的處理可以變更為NOT的方式或者(大于 OR 小于)的方式.

(2) 下面的例子中, ‘||’是字符連接函數(shù).就象其他函數(shù)那樣,停用了索引.
    不使用索引: SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME||ACCOUNT_TYPE=’AMEXA’;
    使用索引: SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME = ‘AMEX’ AND ACCOUNT_TYPE=’ A’;

(3) 索引對(duì)函數(shù)的限制,避免在索引列上使用計(jì)算:
    下面的例子中, ‘+’是數(shù)學(xué)函數(shù).就象其他數(shù)學(xué)函數(shù)那樣,停用了索引.
    不使用索引: SELECT ACCOUNT_NAME, AMOUNT FROM TRANSACTION WHERE AMOUNT + 3000 >5000;
    使用索引: SELECT ACCOUNT_NAME, AMOUNT FROM TRANSACTION WHERE AMOUNT > 2000 ;
    
    注意: 對(duì)在WHERE子句中經(jīng)常要使用函數(shù)時(shí),應(yīng)該建立基于函數(shù)的索引,且只有當(dāng)查詢(xún)語(yǔ)句包含該函數(shù)或者表達(dá)式時(shí),基于函數(shù)的索引才會(huì)被調(diào)用飒赃。

(4) 避免在索引列上使用IS NULL和IS NOT NULL:
    因?yàn)榭罩挡淮嬖谟谒饕兄?所以WHERE子句中對(duì)索引列進(jìn)行空值比較將使ORACLE停用該索引. 
    一般對(duì)要建立索引的列不要設(shè)置為可空利花,如果確實(shí)含有空值科侈,建議使用默認(rèn)值代替空值.

(5) 注意通配符%的影響 
    使用通配符的情況下Oracle可能會(huì)停用該索引。

(6) 避免改變索引列的類(lèi)型
    當(dāng)比較不同數(shù)據(jù)類(lèi)型的數(shù)據(jù)時(shí), ORACLE自動(dòng)對(duì)列進(jìn)行簡(jiǎn)單的類(lèi)型轉(zhuǎn)換.
    假設(shè) EMPNO是一個(gè)數(shù)值類(lèi)型的索引列.
    SELECT … FROM EMP WHERE EMPNO = ‘123’
    實(shí)際上,經(jīng)過(guò)ORACLE類(lèi)型轉(zhuǎn)換,語(yǔ)句轉(zhuǎn)化為:SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123’)
    幸運(yùn)的是,類(lèi)型轉(zhuǎn)換沒(méi)有發(fā)生在索引列上,索引的用途沒(méi)有被改變.

    現(xiàn)在,假設(shè)EMP_TYPE是一個(gè)字符類(lèi)型的索引列.
    SELECT … FROM EMP WHERE EMP_TYPE = 123
    這個(gè)語(yǔ)句被ORACLE轉(zhuǎn)換為:SELECT … FROM EMP WHERE TO_NUMBER(EMP_TYPE)=123
    因?yàn)閮?nèi)部發(fā)生的類(lèi)型轉(zhuǎn)換,這個(gè)索引將不會(huì)被用到!

(7) 索引的一些“脾氣” 
    a. 如果檢索數(shù)據(jù)量超過(guò)30%的表中記錄數(shù).使用索引將沒(méi)有顯著的效率提高. 
    b. 在特定情況下, 使用索引也許會(huì)比全表掃描慢, 但這是同一個(gè)數(shù)量級(jí)上的區(qū)別. 而通常情況下,使用索引比全表掃描要塊幾倍乃至幾千倍!     
22. 避免使用耗費(fèi)資源的操作

帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語(yǔ)句會(huì)啟動(dòng)SQL引擎執(zhí)行耗費(fèi)資源的排序(SORT)功能.通常,帶有UNION,MINUS ,INTERSECT的SQL語(yǔ)句都可以用其他方式重寫(xiě).

23. 優(yōu)化GROUP BY (強(qiáng)烈推薦!!!)

提高GROUP BY語(yǔ)句的效率,可以通過(guò)將不需要的記錄在GROUP BY之前過(guò)濾掉.

參考文章:

https://www.cnblogs.com/wanghang/p/6299429.html
https://www.cnblogs.com/cxxjohnson/p/5686715.html
https://blog.csdn.net/holandstone/article/details/51473010

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炒事,一起剝皮案震驚了整個(gè)濱河市臀栈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挠乳,老刑警劉巖权薯,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異欲侮,居然都是意外死亡崭闲,警方通過(guò)查閱死者的電腦和手機(jī)肋联,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)威蕉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人橄仍,你說(shuō)我怎么就攤上這事韧涨。” “怎么了侮繁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵虑粥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宪哩,道長(zhǎng)娩贷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任锁孟,我火速辦了婚禮彬祖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘品抽。我一直安慰自己储笑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布圆恤。 她就那樣靜靜地躺著突倍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盆昙。 梳的紋絲不亂的頭發(fā)上羽历,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音淡喜,去河邊找鬼壶愤。 笑死缅叠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的祷愉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钳枕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起润歉,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颈抚,沒(méi)想到半個(gè)月后踩衩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贩汉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年驱富,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匹舞。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褐鸥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赐稽,到底是詐尸還是另有隱情叫榕,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布姊舵,位于F島的核電站晰绎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏括丁。R本人自食惡果不足惜荞下,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望史飞。 院中可真熱鬧尖昏,春花似錦、人聲如沸祸憋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蚯窥。三九已至掸鹅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拦赠,已是汗流浹背巍沙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荷鼠,地道東北人句携。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像允乐,于是被迫代替她去往敵國(guó)和親矮嫉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子削咆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容