60-80% of database performance issues are related to poorly performing SQL。60-80%的資料庫性能問題要歸結于生産中糟糕的SQL語句!
以此一文來總結筆者近10多年來的工作經驗并基于最主要的也是最有效的對于Oracle資料庫中的RBO、CBO、索引、WHERE條件進行解說同一時候配以大量案例來幫助讀者從此文中學到的相關的理論知識高速的運用到其正在從事的生産環境中的優化過程中去。
優化的理論基礎

通過Select Count(?)進入優化之旅
不看百度或者GOOGLE說出以下3者的差别?
SELECT COUNT (*)
SELECT COUNT(1)
SELECT COUNT(字段名)
SELECT Count(?
)的知識
ORACLE的優化器
要說PLSQL優化,我們先須要來好好說一下Oracle優化器的知識:
優化器的優化模式
CBO模式
RBO模式
一起來看看oracle優化器的發展曆程
是以。我們知道ORACLE10後開始預設使用CBO。在CBO時ORACLE會自己主動來選擇最優的運作計劃,有時我們會覺得:這個應該走索引更好啊。可是對于CBO來說。一個FULL TABLE ACCESS反而比索引更有效。
是以。在CBO的模式下,我們須要做的就是:
- 做好資料庫資訊的相關統計
- 合理建設我們的索引
- 優化我們的SQL
讓我們從索引的基本知識下手吧
索引是不須要改動SQL最直接帶來性能提升的利器,何時該建索引,怎麼建?怎麼樣讓你的索引更合理?
索引按内部結構分類
索引按功能分類
索引按索引對象分類
建立索引的方法論
上面介紹了這麼多索引的分類,以下來講講建立索引的方法論吧。大家可能較關心這個。由于這個是經驗總結也是實戰實用的利器哈。
不建議建立索引的情況
索引非常奇妙,可是索引不是萬能,有時你建了索引也等于沒用或者是白建、作無用功,為什麼呢?我們看下去。
索引不會生效的情況
是以索引不要亂建,有時建了也是白建。為什麼呢?來看看以下的案例分析吧:
以案例來說明
PLSQL優化>一個不走索引的優化案例
這個樣例說明了。假設你有一字參于WHERE條件查詢的字段。可是它參于了運算符,是以它在ORACLE的内部運作計劃中是不會走索引的。是以我們做了一個小小的變化。效率提升了多少倍?5.3倍,530%。呵呵!
以上例我們能夠為建立索引作一個總結。
建立索引的總結
Table Analyze
Analyze Table VS DBMS_STATS
Import & Export
說到Import & Export指令,大家會說。。。哎,這個不是非常easy,就是:imp username/pwd@oraid file=path 嗎?嘿嘿。。
。
試想:
- 你須要導入一個8GB左右的.dmp檔案進入資料庫
- 你須要将一個庫,當中含有至少30張表而且每張表都超過1200萬條記錄的資料進入一個.dmp檔案
然後你去試試看這個耗時。
Import的正常做法
這是一個真實的案例。我們在CCC即世界著名車險公司項目中。我們定期會和CCC芝加哥總部同步一個8GB左右的.dmp檔案進入我們的資料庫,由于安全原因是以須要依靠.dmp交換檔案的形式于零晨同步至中國的資料庫,而且在T+1第二天早晨的8:00前完畢同步。
于是。我們的DBA開始來了。。
。。。
從零晨到第二天早上8:00,硬是沒有導完,一查,資料庫中session已經逾時了,連續2天還是這樣。
于是,我們把原有的語句稍稍作了一下變化:
僅僅是把原來的一句imp折成了2條:
- 第一條,僅僅導資料,不導索引。而且設定成10000條資料一次commit,同一時候設定了一個緩沖池
- 第二條,僅僅導索引。不導資料。而且設定成10000條資料一次commit,同一時候設定了一個緩沖池
結果讓人驚歎。。。發覺最後僅僅用了40分鐘不到,兩條語句所有運作完畢。完畢了導入。。
。事實上這個原因我能夠用以下2個樣例來說明:
- 一個含有8GB檔案内容的檔案夾,用FTPclient下載下傳,你會發覺似乎永遠等不到頭,幾小時就這樣耗着,然後你改成先把這個檔案夾打成一個壓縮包,然後再用FTPclient 下載下傳。幾十分鐘就能搞定。
-
你用JDBC寫一個FOR循環插入100萬條記錄。
。結果是ORACLE直接爆掉。而你採用批量送出。。。結果是驚人的!
事實上我們當時所做的折分,原理如同上述兩個案例,是一樣的道理,降低IO讀寫,設定緩沖,批量送出。假設你的事務太大。
。。。。
以案例來說明PLSQL的優化
PLSQL優化-SELECT IN 與SELECT EXISTS
這邊提高了多少?光看IO就知道提高了多少了,呵 呵,非常好玩吧?再來!
PLSQL優化-SELECT IN的幾種優化
PLSQL優化-SELECT IN、OR、UNION的互轉
看看3次改動,最後一次。提升了多少倍?11.2850-0.0261再除以0.0261=431.375,431.375倍。。。。。。一條SQL啊。
。。
在寸土寸金的網際網路應用中,單條SQL提高了431.375倍。。。這是什麼概念。!!
你好讨厭。!!再來。!!
PLSQL優化-分頁語句中增加索引的優化
以下是一條分頁語句,我們對created_date做一個索引,等。。。。。。等等等,這邊的索引不是一般的索引。我們把圖形化工具建的索引翻譯成SQL:
create index IDX_WAREHOUSE_CT on T_WAREHOUSE(CREATED_DATE DESC);
我們這個表是一個含有1000萬條記錄的表,僅此一招。整個SQL查詢提高了300%-340%
PLSQL優化-INNER JOIN VS WHERE
PLSQL優化-WHERE語句優化要點
注意以下這個樣例。僅僅是WHERE條件後的順序上下颠倒一下。就提高了10倍的效率,呵呵。
WHERE語句中選擇最有效的表名順序
好玩吧!
!!再來!
!!
PLSQL優化-用UNION代替OR
看看以下這個樣例吧:
是不是寫SQL時略微注意一下。。。這個效率。
。這個性能 。。。123%。
123%的提高啊。
PLSQL優化>共享SQL
前面我們用好幾個執行個體說了一下PLSQL中最主要的一些性能上能夠帶來的提升。這邊我們須要提一下ORACLE自帶的一個緩沖SQL結果集命中率的工具
是以。我們在寫SQL時要用JAVA的PreparedStatement,要用:1這種東西來做傳值,由于ORACLE是自帶SQL緩沖池的,另外在此要多說一句的是。盡管ORACLE10後開始帶有ASM(自己主動記憶體管理)。但有時ASM不是萬能,對于一些大形站點,有時我們的DBA是須要手工去調整ORACLE的SGA,即:
是以,這對我們的ORACLE DBA來說提出了更高的要求。
PLSQL優化的基礎掌握了上述幾點,基本能夠讓你的系統性能提高2位數-3位數。興許感興趣的讀者還能夠繼續去看:
怎樣自學
對于ORACLE的PLSQL相關調優該怎樣自學呢?
是不是非常自虐哈。
那我們就用著名的Opensource界的一句銘言:play by yourself, play with it。
用中文來說那就是:自虐着并快活着。
要成為“東方不敗。