這是我給公司同事作的內部培訓ppt的講義,給你們分享一下。這是培訓大綱,ppt在找地方上傳,等找到了會把連接發在這裏 。算法
暫時放在csdn上,賺點下載積分:https://download.csdn.net/download/kingstarer/10655069sql
截幾個ppt頁面你們能夠先預覽一下數據庫
你們好,歡迎你們來參加今天的技術交流,而今天打算跟你們分享的是oracle數據庫應用優化相關的一些經驗。這是大綱。緩存
咱們今天要講的內容分五部分。其中1到3是咱們今天重點交流的內容,而後四和五的話就可能,稍微快一點就帶過。服務器
我先給你們簡單介紹一下每一個部分的內容。架構
首先第一部分會給你們介紹一下oracle數據庫的架構及一些內部實現細節。這是爲了給後面介紹數據庫優化知識作一些鋪墊。oracle
接着,我想給你們介紹一些編寫高性能sql的經驗。工具
而後在第三部分,咱們會分享一下數據庫的執行計劃相關知識。咱們平時發現sql跑得比較慢時,就能夠查看執行計劃,找出裏面不合理的環節進行優化。性能
第四部份內容是關於數據庫等待事件及awr報告的一些優化的內介紹。awr報告至關於數據庫的體檢報告,等待事件就是一些體檢指標。咱們作整個數據庫應用優化常常用到它。學習
第五部分的話是一些學習資料推薦。
下面咱們開始進入第一部份內容的介紹。這是,一個oracle數據庫的架構圖。
這裏user process是客戶端進程的意思,也就是咱們平時本身寫的程序,或者sqlplus sqldevelor這些工具。
咱們平時說的數據庫是一個比較模糊的概念,其實它是包含兩部分組成。一部分是數據庫文件,包括數據文件,日誌文件等。也就是這一部分,這個纔是專業術語的數據庫database。 另外一部分是數據庫實例,一套圍繞真數據庫運行的進程集合。
這裏要說明一下的是,不是比較舊的,我從網上抄下來的11g架構圖。如今數據庫都已經出到18c了,可能會有一些變化。另外,這圖裏面有一些不是過重要的數據庫進程,這裏是沒有發出來的。嗯,咱們仍是看這張圖吧,這圖估計是oracle8i時出的圖,雖然比剛纔的圖缺乏了一些內容,但我以爲畫的更好一些,因此後面會圍繞這張圖來介紹。
從這圖能夠看出來,oracle數據庫主要分兩部分,一部分是數據庫實例,由數據庫後臺進程和相關的共享內存組成。另外一部分,就是DataBase這一塊,主要是數據庫文件。咱們常說的數據庫是對這兩塊內容的統稱。
這圖仍是挺重要的,你們多看幾眼。接下來咱們會對這圖裏面出現的名詞作一些詳細介紹。
接下來,咱們對數據庫的一些重要組件,逐個介紹吧。
首先要介紹的是數據庫實例這塊。這一塊由兩大部分組成,一個是這個,巨大的共享內存塊,咱們稱之爲SGA。另外一塊是oracle後臺進程。
SGA是很是重要的概念。它主要是作爲oracle庫表數據和重作日誌的緩存和緩衝。下一頁咱們會詳細講裏面具體細節。
這一頁咱們重點要介紹的是oracle數據庫後臺進程。這些後臺進程主要負責數據庫監控,數據與日誌讀寫,故障恢復等功能。
這裏咱們列出幾個比較常見的進程介紹。 Pmon和smon,這兩個進程分別用與用戶進程故障和系統故障恢復的。咱們開發通常不須要關心它的工做原理,dba才須要關注。
DBWN這個進程負責把SGA裏面的數據寫回磁盤。咱們剛纔說過SGA緩存了oracle數據庫表數據。裏面有部分數據是用戶用sql修改過的,須要寫回磁盤。由於數據庫寫磁盤比較耗時,因此數據修改老是先在SGA中修改,達到必定量或者數據庫空閒時才由DBWN統一寫回磁盤。
LGWR也是一個比較重要的進程。它負責把Redo日誌從內存中寫到磁盤,用於數據庫恢復。一個事務只有將Redo日誌寫到磁盤才能算完成。LGWR主要工做時間點是用戶發起commit命令時,或者日誌緩衝區超過1M時工做。
Redo日誌大小有限制,寫滿後會經過歸檔日誌進程轉移到歸檔日誌裏面。
CHKP是協調LGWR和DBWN的進程。詳細協調原理你們有興趣能夠上網找找,我這裏主要想介紹它們之間協調須要用到的一個概念,叫系統變動號,也就是這個SCN。這個系統變動號咱們能夠簡單理解爲是oracle事務的編號,它是隨着事務提交與時間變化而增加的。Oracle每一個數據塊都會記錄修改該數據塊的系統變動號。數據庫作查詢時,能夠根據這個系統變動號判斷記錄是否已經最近被修改過。
下面詳細介紹一下SGA的組成。
數據庫塊緩衝緩存區,這個主要是緩存數據庫的數據的。包括讀寫數據,都會先放到這個緩衝區,有空再寫回磁盤。通常交易系統這個緩衝區的命中率是很高的,超過90%。
Library Cache是一個緩存,但它緩存的不是數據,而是sql以及執行計劃。Oracle數據庫在執行sql前,先要生成sql的執行計劃,也就是sql的詳細執行步驟。這個步驟生成是相對比較消耗數據庫資源的。因此oracle會把生成的執行計劃暫存起來,後面若是碰上如出一轍的sql,就直接用現成的執行計劃,不用再從新生成。因此咱們平時寫sql常常說要用綁定變量,一個主要緣由就是減小數據庫執行計劃生成的時間。
重作日誌剛纔有稍微提到,它是數據庫變動的記錄。例如咱們發出一個update語句,把一個字段從0變成1,redo日誌就會記錄這個字段變成1以後的數據。數據庫修改一條記錄後不會當即寫回磁盤的,而是先寫到緩存同時登記重作日誌。在事務提交時,只要把重作日誌輸出到磁盤,這條記錄就不會由於斷電丟失。由於通常來講,寫數據時隨機IO,寫日誌是順序IO,順序IO速度比隨機IO快不少。
與Redo日誌對應的是Undo數據。它是存放個Undo表空間。Undo就是撤銷,與重作是相反的過程。因此咱們把字段從0變成1時,這裏會記錄的是字段在改變前,仍然是0的數據。
注意Undo表空間的數據是存放在數據庫文件的,因此數據庫在操做回滾段時也會在Database Buffer Cache進行緩存。
Undo數據有一個很是有用的做用,就是一致性讀。Oracle執行select語句時通常是不鎖表的,可是它仍是會保證返回的數據確定是查詢開始時間點的數據,即便查詢過程當中,數據被修改過。這功能實現就是須要經過查詢回滾數據,得到數據在修改前的狀態。
這是檢查點的原理,檢查點是用於數據庫斷電恢復的。你們有興趣本身細看。
數據庫實例介紹完,下面咱們開始介紹Database這塊。Database是數據庫文件集合的統稱,一個Database能夠對應多個數據庫實例。咱們常說的rac就是這樣,多個數據庫服務器,操做同一個數據庫文件。
數據庫裏面最重要的文件就是數據文件和聯機日誌文件。剛纔咱們有介紹過Redo日誌緩存,它在用戶提交事務時就會寫到磁盤,就是這個聯機日誌。
這一頁介紹的是oracle數據庫服務進程的知識。也就是處理咱們平時寫的客戶端程發出的sql請求的進程。
一個數據庫會有不少個服務進程,這些進程共同享一個SGA。但每一個進程都有本身的一塊私有內存空間,咱們稱之爲PGA。PGA默認是比較小的,若是咱們須要進行大表鏈接,可能會嫌內存不夠用,這時咱們能夠申請把PGA加大。作批量任務的同窗能夠注意一下。
可是有兩部分SB哎,就是這一塊的內存,而後呢?他還有另一部分就是這個這些相關的一些後臺進程是比較重要的,這是一塊巨大的共享內存,而後呢?它主要的功能的話就是作一個化充實這樣這些數據快讓咱們愉快這些都會在裏面存,而後這個數據是這些後臺進程,後來進程,包括上面這幾個,這個是每個進程具體佈置的東西監控的這個不是過重要,而後這個這個屁嗎?這個是用戶進程監控這個主要用於掛了的話就沒有正常斷開的狀況下,他會幫你把這些原來重要,而後這個這個事,let這個這個這個做用的話是吧,就咱們曾說過,裏面有幾塊就是把數據庫緩存的一些數據寫回,而後呢。這個night。我只要。駛入池塘。日誌寫入進程就是跟咱們數據庫在按期。寫到日誌文件。這個是匡威。歸檔歸檔進程,這個呢是這個適用於這裏面其實比較重要的話,就是須要關心的是這兩個進程,不要進程的相關知識。這裏。這裏是oracle數據庫的一些原理。這是系統改編號,就這個事,日誌進程他。他有時候。接下來咱們介紹這一塊數據庫相關的知識。
下面讓咱們經過一個update語句的執行過程介紹來串講剛纔介紹過的知識吧。首先,客戶端會發起sql執行請求,數據庫會到緩衝池裏面查找該sql執行計劃是否存在。若是存在則使用現成的執行計劃,這個過程稱爲軟解析。若是執行計劃不存在則須要從新生成,這個過程叫硬解析。接着數據庫會分析sql須要訪問的數據,看是否在數據塊緩存裏面。若是是則直接使用緩存數據,若是不是則須要從數據庫文件讀出來放到內存。
接着數據庫會在內存中修改數據塊,而且同時登記redo日誌到日誌緩衝區。
等到數據庫提交時,redo日誌的內容就會被刷進磁盤。數據緩衝區的內容則過一段時間由dbwn寫進磁盤。
關於數據庫的主要架構介紹到這裏。 這幾頁是數據庫塊的細節知識介紹,因爲時間關係就不講了。你們主要須要知道,oracle一次硬盤操做都是以數據庫塊爲單位的,而不是以一行記錄或者一個字段爲單位的。一個數據庫塊會有n行記錄。
下面進入重點交流的內容,關於數據庫應用優化的知識。
首先,咱們在數據庫優化時要注意系統的類型,不一樣系統的優化目標是不同的。通常來講,咱們把系統分爲兩大類:OLTP和OLAP,也稱DSS。
OLTP全稱是在線交易系統,像咱們的收單聯機系統就屬這類。這類系統的特色是:交易很是頻繁,但每次交易涉及的數據量不多。對數據庫響應時間要求比較高,通常要求幾秒甚至幾毫秒內返回。
OLAP全稱是聯機分析系統,咱們平時作的批量系統就屬這類。這類系統特色時:交易比較少,但每次交易涉及數據量比較多。數據庫訪問時間要求相對寬鬆點。
Oltp系統常見資源瓶頸是在cpu和內存上,而oltp系統常見問題是出在io上面。
這個表格介紹了兩類系統開發的一些經驗。
OLTP因爲sql運行頻次較高,通常要求使用綁定變量,減小數據庫生成執行計劃的消耗。另外,OLTP通常要儘可能減小訪問數據庫磁盤的次數,儘可能提升內存命中率。
在線分析系統通常是讀寫比比較大的系統,爲了數據訪問方便會作不少冗餘。而且,爲了數據庫能得出最優的執行計劃,使用綁定變量會少一些。
這是通常兩類系統在裝數據庫時的參數配置差別,也是遵循系統業務特色而配置的。
前面一節介紹了系統優化的整體原則,這裏會介紹一些優化細則。
首先是關於索引的。
索引告訴數據庫有什麼,而不是沒有什麼。因此咱們平時用的不等於查詢條件是用不上索引的。
另外,索引列的數據類型咱們也要注意。像這種狀況tel電話號碼列用的是字符串類型,但查詢時倒是用tel=數字這樣的。會致使數據庫索引無效。還有,像這種,咱們看起來是數學等價的操做,但卻會由於索引的問題致使效率相差不少。
還有這個也是常見誤區。不是使用索引不必定比不使用索引快。按咱們平時經驗,數據庫裏面少於100條記錄,或者索引列選擇比不高,例如性別字段只有男或者女,使用索引反而慢一些。由於數據庫使用索引查詢時須要先在索引裏面作幾回磁盤操做,而後找到記錄位置後還要再回表數據訪問記錄內容。
這條經驗也比較重要,若是咱們數據庫裏面有使用外鍵保證數據一致性,那要注意在建了外鍵的列上建索引。由於oracle修改父表記錄時須要到子表檢查修改後記錄是否會違反外鍵約束,不建索引會很耗時。
這一頁想介紹的是oracle一些特性,這是oracle獨有功能。用好這些特性能夠在某些特定場景大大優化咱們程序。
這一條,講的是oracle的rownum和rowid用法。咱們平時寫腳本常常會出現這樣的場景:若是庫表有記錄,則執行a操做,不然執行b操做。有些同窗會很天然地用select count(*)來判斷庫表是否有記錄。其實咱們能夠在後面加上where rownum < 2這樣的限制,這樣作是告訴數據庫只要找到符合條件的記錄就能夠結束查詢,不須要統計完全部數據。
Rowid概念前面的ppt頁有,使用rowid訪問記錄是oracle訪問數據最快的方法,由於rowid明確表達了數據在磁盤哪一個文件,哪一個數據塊,哪行記錄。比索引訪問要快,用索引訪問時須要先查出rowid再根據rowid查對應的數據。
還有這個技巧,相信作批量的同窗也常常用到。就是使用一些特殊方法讓數據庫不要記錄redo日誌。前面咱們介紹過,對數據庫操做都須要記錄redo日誌用於數據庫出現異常時恢復數據,但若是咱們肯定數據不是過重要,數據庫異常掛掉後不須要恢復,則可使用這些小技巧減小redo日誌以加快速度。
還有一些其它不成體系的技巧,這裏也介紹一下。
這個是你們比較熟知的,使用綁定變量,能夠複用sql執行計劃,減小數據庫cpu消耗。
這個技巧你們應該也知道,就是刪除整個表數據時,儘可能考慮使用truncate。由於truncate是直接修改數據庫字典,把庫表佔用數據空間狀態改成未使用。這樣操做是很快的。不過要注意的是truncate不像delete,誤刪後能夠回滾。Truncate一執行後就會自動提交事務,而且沒法閃回查詢。
接下來這一大章想要給你們交流的是關於數據庫執行計劃的一些知識。前面一章介紹的一些優化經驗,這一章說的是一個優化的通用方法:經過調整執行計劃改善sql運行效率。
首先介紹一下執行計劃的定義。執行計劃就是數據庫執行sql語句的步驟計劃,oracle在執行sql以前會先將複雜sql拆解成一些簡單步驟並依次執行。
同一個sql能夠有不少個不一樣的執行計劃,這些執行計劃效率差異可能很大。
咱們怎麼看sql的執行計劃呢,這裏介紹幾個方法:
一個方法是在sqlplus裏面執行set autotrace on,而後再執行sql,執行完畢後sqlplus就會打印sql執行計劃及一些統計信息。
還有一種,不須要執行sql,只須要執行explain命令,接着就能用sql語句查出它的執行計劃。
還有一種,我比較經常使用的方法。在plsql develor的執行計劃窗口中運行sql,也能夠顯示執行計劃。就像這邊這個圖片同樣。
知道怎麼看執行計劃後,咱們還要懂得怎麼分析。
咱們看這個簡單的sql的執行計劃,能夠看出來,執行計劃是樹型結構,有不少個步驟組成,每一個步驟均可能有子結點或者兄弟結點。
咱們看執行計劃時須要從上往下看,碰到有子結點前後子結點,若是沒有子結點,則同一層級的兄弟結點中比較靠上的一個,看完再看另外一個。
或者咱們能夠藉助工具來幫咱們肯定執行計劃執行順序。這個就是plsql裏面看執行計劃的窗口,這裏有一組箭頭,點擊它會依照執行順序選中執行步驟。
咱們拿一個具體案例作一下講解:
這個sql做用是從僱員表裏面找出工號小於103的數據,關聯職位表取出職位信息,關聯部門表取出部門信息。
它對應的執行計劃是這樣的
咱們從上往下看,0 1 2都有子結點,因此先看它們的子結點。一直看到3,3沒有子結點,因此先執行3。從僱員表裏面取出數據。
3執行完後須要執行它的兄弟結點4,4有子結點,因此先執行它的子結點5,用job_id到索引job_id_pk裏面找數據的rowid。5執行完後會根據找到的數據rowid回到職位表裏面找出職位信息,也就是4這個子節點的操做。
3和4執行完後就要回到2,把數據鏈接到一塊兒。而後再執行6和7,從部門表裏面取出數據,接着執行1再把部門數據跟前面的僱員與職位錶鏈接結果再合併,最後回到0,返回客戶端。
因此這個執行計劃的執行順序就是3 5 4 2 7 6 1 0
像這個是比較複雜一點的執行計劃,你們有興趣能夠本身回去看它的執行順序。答案在這一列。
前面咱們說過,同一個sql會有不少不一樣執行計劃。那數據庫怎麼肯定使用哪一個執行計劃呢。這就涉及這章要介紹的,優化器的概念。
優化器是數據庫的一個核心組件,負責將sql根據各類判斷標準轉換成最優的執行計劃。
如今咱們用的優化器都是cbo,基於成本計算的優化器。它會計算每一個sql執行步驟的成本,挑選總成本最低的執行計劃。
前面咱們說過,oltp和olap系統優化目標是不一樣的,一個是注重響應速度,一個是注重資源消耗。因此oracle也爲cbo提供了兩種工做選項,一種是first_rows,適用於oltp系統,另外一種是all_rows,適用於olap系統。
兩種模式下,同一個sql選擇的執行計劃可能相差很大,致使運行消耗的時間資源也大不相同。
爲何不一樣執行計劃會致使差別這麼大呢,主要是因爲數據庫錶鏈接方式不一樣形成的。
這是oracle常見的四種數據庫表關聯方式。
咱們看剛纔的sql執行計劃,這裏的1和2都是將兩個數據源進行關聯。
這裏關聯方式都是使用嵌套關連。嵌套關聯的原理是依次取出驅動表的記錄到內層表尋找符合條件的鏈接數據。顯然,這種狀況下要內層表查找起來比較快,有索引或者記錄數比較少。並且外層表數量越少越好,這樣能夠減小到內層表查數據的次數。
嵌套關聯有一個好處,能夠很快的返回符合條件的前幾條記錄。因此通常oltp系統使用嵌套關聯比較多。
Oracle還有一個比較經常使用的鏈接方式,就是這個哈希鏈接。哈希鏈接原理是先將一個表在內存中作成哈希表,接着訪問內層表的數據,逐個到哈希表裏面查看是否有對應。
哈希鏈接適用於內層表沒有索引,或者鏈接兩個表記錄都相對比較多的狀況。Oltp系統用這種鏈接方式比較多。
因爲鏈接算法不一樣,對系統資源消耗和響應時間也會有很大差別。
Oracle還有其它兩種鏈接方式,但平時用得很少,這裏不說了。
除了鏈接方式外,數據訪問方式也是執行計劃效率差別的主要緣由。
仍是舉剛纔的例子,這裏面有好幾種數據訪問方式,對不一樣表採用了不一樣的方式。
有全表掃描,也有索引掃描。
全表掃描,顧名思義,就是對整個表的數據依次掃描。通常要求表的數據量比較少,或者符合查詢條件的數據佔全表數據比例較大的狀況。
索引訪問,跟全表掃描就相反了,適用於表數據量比較大,而符合條件的數據比較少的狀況。
索引訪問的方式有這五種,從上到下消耗的資源依次增大。
索引惟一掃描 適用於where條件直接指定主鍵的狀況
索引範圍掃描 適用於大於,小於這種where條件
索引全掃描 與全表掃描相似,它是掃描整個索引的數據。應用場景是索引字段能包含select返回字段的狀況
索引快速全掃描 就是快速的索引全掃描,由於快,因此可能返回的是無序的記錄。索引默認是有序的
索引跳躍掃描 適用於where條件沒有指定索引前導列的狀況,而且前導列選擇性比較低的狀況。例如建了性別和姓名的聯合索引,但查詢時只限制了姓名爲黃詞輝,沒限制性別。Oracle會分別查詢女性的黃詞輝和男性的黃詞輝,把結果合併起來
咱們平時看的執行計劃主要就是查數據並鏈接,掌握了它們的原理,咱們就能夠靠本身的開發經驗來判斷這個執行計劃是否足夠優化。
=============================================================
若是以爲這篇文章對你有用,掃個支付寶紅包或者打賞幾毛錢吧^_^,寫這文章也費也很多力氣。您的支持是我最大鼓勵。