oracle 優化相關
--選擇最有效率的表名順序:
Oracle的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最先處理,
在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連線查詢,
那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表。
--WHERE子句中的連線順序:
Oracle採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連線必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。
--select 子句中避免使用*
Oracle在解析的過程中, 會將‘*’依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味著將耗費更多的時間
--用Where子句替換HAVING子句
HAVING 只會在檢索出所有記錄之後才對結果集進行過濾,而Where子句在檢索時過濾
on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最後
--用EXISTS替代IN、用NOT EXISTS替代NOT IN
在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接。在這種情況下,使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。
在子查詢中,NOT IN子句將執行一個內部的排序和合並。無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)。
為了避免使用NOT IN ,我們可以把它改寫成外連線(Outer Joins)或NOT EXISTS。
--SQL語句用大寫的;因為Oracle總是先解析SQL語句,把小寫的字母轉換成大寫的再執行。
--在Java程式碼中儘量少用連線符“+”連線字串。
一個'+'就會產生一個新物件
--用>=替代>:
高效:SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3
兩者的區別在於,前者DBMS將直接跳到第一個DEPT等於4的記錄而後者將首先定位到DEPTNO=3的記錄並且向前掃描到第一個DEPT大於3的記 錄。
--避免在索引列上使用NOT、IS NULL和IS NOT NULL:
NOT會產生在和在索引列上使用函式相同的影響。當Oracle“遇到”NOT、IS NULL和IS NOT NULL,他就會停止使用索引轉而執行全表掃描。
--避免在索引列上使用計算。
WHERE子句中,如果索引列是函式的一部分。優化器將不使用索引而使用全表掃描。
避免對索引欄位進行計算操作
避免在索引欄位上使用not,<>,!=
避免在索引列上使用IS NULL和IS NOT NULL
避免在索引列上出現數據型別轉換
避免在索引欄位上使用函式
避免建立索引的列中使用空值。
--用UNION替換OR (適用於索引列):
通常情況下,用UNION替換WHERE子句中的OR將會起到較好的效果。對索引列使用OR將造成全表掃描。
注意,以上規則只針對多個索引列有效。如果有 column沒有被索引,查詢效率可能會因為你沒有選擇OR而降低。
--總是使用索引的第一個列:
如果索引是建立在多個列上,只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引。
這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略 了索引。
--‘||'是字元連線函式、‘+'是數學函式。就象其他函式那樣, 停用了索引。
--相同的索引列不能互相比較,這將會啟用全表掃描。
--模糊查詢like
%yue%,由於yue前面用到了“%”,因此該查詢必然走全表掃描,除非必要,否則不要在關鍵詞前加%。
--不要以字元格式宣告數字,要以數字格式宣告字元值。(日期同樣)否則會使索引無效,產生全表掃描
使用 :SELECT emp.ename, emp.job FROM emp WHERE emp.empno = 7369;
不要使用:SELECT emp.ename, emp.job FROM emp WHERE emp.empno = ‘7369’
--LEFT JOIN 和 inner join
是否真的需要left join,否則選用inner join 來減少不必要的資料返回。
連表查詢n*m,那麼減少基礎表的記錄數目可以有效的提高效率(把查詢條件放入到基礎表先進行過濾,然後在進行連線)
select top 500 * from
(select * from [dbo].[table1] where (ss between @a1 and @a2)) a
LEFT JOIN dbo.[table2] ON a.m = dbo.[table2].n
--應避免在where子句中使用or來連線條件,否則引擎將放棄使用索引而進行全表掃描
--應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:trim()