1. 程式人生 > >Oracle與Mysql等資料庫通用SQL優化技巧

Oracle與Mysql等資料庫通用SQL優化技巧

a. 資料表的處理順序


oracle 在解析一個查詢語句FROM後面的一系列資料表是按照從右往左的順序進行的.也就是說最後的資料表將是最先被oracle處理的,所以我們在寫多個表關聯的查詢語句時,把資料量最小的表或者是經過條件篩選後得到資料量最小的表放到最後,資料量大的表就放在最前面.


select col1, col2 from t1, t2 where t1.id = t2.id  and t2.sex = 'male';


上面的語句中資料表t2是第一個被oracle處理的資料表,然後就是t1.


b.where 條件的處理順序


oracle 在解析查詢語句制定執行計劃時,針對where後面的查詢條件的解析是按照從下往上的順序進行的.也就說查詢的子條件越處於where的後面,它被oracle處理優先順序就越高.所以我們可以把能過濾大量資料的條件放到最後,讓oracle優先處理它從而返回一個最小資料集,好讓oracle在後續的過濾工作基於該最小資料集進行,來縮小整個查詢時間.


select col1, col2 from t1, t2 where t1.id = t2.id and t2.sex = 'male' and t2.etime>=trunc(sysdate-1) and t2.etime


上面語句中的查詢條件t2.channel = '0' 將會被oracle最先解析.


第二:查詢方式的錯誤選擇導致效率低下


平時工作下來積累的一些優化建議如下:


1. where 後面的條件儘量避免涉及null值得判斷,為什麼呢?那是因為一旦涉及到了null的判斷,oracle將不會走該欄位所涉及的索引而觸發全表掃描.


select col1 from t where t.servid is not null; --效率低


如果t表的servid中有索引的話,那麼本次查詢將拋棄索引,走全表掃描.建議如果真的需要判斷的話,可以定義該欄位的預設值為0或者其它值.


2. where 後面儘量不要使用多個or把條件組合起來, 可以使用union/union all來實現


select col3, col5 from t where (t.servid = 5 or t.servid = 90) and t.channel = 1; --效率低


select col3, col5 from t where t.servid = 5 and t.channel = 1


union


select col3, col5 from t where t.servid = 90 and t.channel = 1;   --效率高


3. 條件中儘量避免給有索引的欄位進行不等操作(!=或<>),因為一旦進行不等操作,oracle將不會走現有的索引轉而走全表掃描.


4. 返回結果使用具體的列名來代替星號(*),因為oracle 遇到星號 需要另外去查對應的字典從而把所有的列名給轉換出來,這導致了需要消耗時間.


5. 訪問資料表的次數儘量少


6. 使用exists 來代替in , not exists 代替not in 來提交資料的訪問速度


7. 不要對有索引的欄位進行函式操作或者運算操作,不然會導致這些欄位不會走索引


select col1 from t where (t.servid * 2) = 10; --效率低下


select col1 from t where t.servid = 10/ 2; --效率高


8. 當需要刪除大量資料的時候,如果條件允許的話,可以使用truncate 來代替delete. 因為delete 時資料庫時需要維護一系列的資訊以便進行回滾等操作,而truncate 則不是要額外維護這些資訊,直接高效清空資料庫表.


9. 如果表有分割槽的話,儘量使用分割槽進行查詢.因為同類的資料都集中在一個分割槽(資料塊)裡面,查詢是不需要跨塊查詢,從而效率較高


10.  比較大小時儘量使用等於號來提高效率


select col1 from t where t.servid > 60; --效率比較低下,因為dml會直接跳到60這個記錄上,然後在往前掃大於60的記錄,額外的動作,額外的消耗.


select col1 from t where t.servid >= 61; --效率高


11. 判斷是否存在某條記錄時,使用exists 來提高效率,它可以避免進行全表掃描


select count(*) from t where t.name = 'Gavin';  --效率低下,進行全表掃描


select count(1) from dual where exists(select null from t where t.name='Gavin'); --效率高


12.  union all 效率高於union ,因為union 相對於union all 來說多了一個去重的操作


13. 可以使用檢視來加速結果的搜尋


14. 如果對有索引的欄位進行模糊搜尋時,儘量使用單右邊模糊匹配查詢,這樣就可以使它能有效的使用對應的索引.


select col5 from t where t.name like '%Ga%'; --效率低,不走索引


select col5 from t where t.name like 'Ga%';  --效率高,走索引