SQL優化的一些實用方法

一、任何在where子句中使用is null或is not null的語句優化器是不容許使用索引的。由於只有該字段中有null值,即便建立了索引其實也
是沒有用的,因此建立索引應該在有值的字段上建立;sql

二、使用該sql語句將不會使用索引:select * from employee where last_name like ‘%cliton%';
   這樣的話會使用索引:     select * from employee where last_name like ‘cliton%';數據庫

三、Order by語句
ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什麼特別的限制,也能夠將函數加入列中(象聯接或
者附加等)。任何在Order by語句的非索引項或者有計算表達式都將下降查詢速度。仔細檢查order by語句以找出非索引項或者表達式,它們
會下降性能。解決這個問題的辦法就是重寫order by語句以使用索引,也能夠爲所使用的列創建另一個索引,同時應絕對避免在order by
子句中使用表達式。安全

四、 選擇最有效率的表名順序(只在基於規則的優化器中有效): 
ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最早處理,在FROM子句
中包含多個表的狀況下,你必須選擇記錄條數最少的表做爲基礎表。若是有3個以上的錶鏈接查詢, 那就須要選擇交叉表(intersection
table)做爲基礎表, 交叉表是指那個被其餘表所引用的表. 網絡

五、 SELECT子句中避免使用 ‘ * ‘: 
ORACLE在解析的過程當中, 會將’*’ 依次轉換成全部的列名, 這個工做是經過查詢數據字典完成的, 這意味着將耗費更多的時間 oracle

六、 減小訪問數據庫的次數,能使用一條sql語句查詢出來的最好使用一條語句直接查詢出來。  整合簡單,無關聯的數據庫訪問: 
若是你有幾個簡單的數據庫查詢語句,你能夠把它們整合到一個查詢中(即便它們之間沒有關係) 函數

七、經過內部函數提升SQL效率.: 複雜的SQL每每犧牲了執行效率. 可以掌握上面的運用函數解決問題的方法在實際工做中是很是有意義的 性能

八、 使用表的別名(Alias): 
當在SQL語句中鏈接多個表時, 請使用表的別名並把別名前綴於每一個Column上.這樣一來,就能夠減小解析的時間並減小那些由Column歧義引發
的語法錯誤. 優化

九、 用EXISTS替代IN、用NOT EXISTS替代NOT IN: 
在許多基於基礎表的查詢中,爲了知足一個條件,每每須要對另外一個表進行聯接.在這種狀況下, 使用EXISTS(或NOT EXISTS)一般將提升查詢的
效率. 在子查詢中,NOT IN子句將執行一個內部的排序和合並. 不管在哪一種狀況下,NOT IN都是最低效的 (由於它對子查詢中的表執行了一個
全表遍歷). 爲了不使用NOT IN ,咱們能夠把它改寫成外鏈接(Outer Joins)或NOT EXISTS. 
例:
 (低效)select * from z_shangbiao u where u.ann_nnum!='' and u.ann_nnum  in( select e.user_account FROM  t_evaluation e)
(高效)select * from t_user u where u.account!='' and EXISTS( select e.user_account FROM  t_evaluation e where
u.account=e.user_account)lua

十、 用索引提升效率: 雖然使用索引能獲得查詢效率的提升,可是咱們也必須注意到它的代價. 索引須要空間來存儲,也須要按期維護, 每
當有記錄在表中增減或索引列被修改時, 索引自己也會被修改. 這意味着每條記錄的INSERT , DELETE , UPDATE將爲此多付出4 , 5 次的磁
盤I/O . 由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢.。按期的重構索引是有必要的.: 設計

十一、用EXISTS替換DISTINCT: 
當提交一個包含一對多表信息(好比部門表和僱員表)的查詢時,避免在SELECT子句中使用DISTINCT. 通常能夠考慮用EXIST替換, EXISTS 使查
詢更爲迅速,由於RDBMS核心模塊將在子查詢的條件一旦知足後,馬上返回結果. 例子: 
(低效): 
SELECT  DISTINCT  DEPT_NO,DEPT_NAME  FROM  DEPT D , EMP E WHERE  D.DEPT_NO = E.DEPT_NO 
(高效): 
SELECT  DEPT_NO,DEPT_NAME  FROM  DEPT D  WHERE  EXISTS ( SELECT ‘X’ FROM  EMP E  WHERE E.DEPT_NO = D.DEPT_NO); 

十二、sql語句用大寫的;由於oracle老是先解析sql語句,把小寫的字母轉換成大寫的再執行 

1三、 避免在索引列上使用計算. 
WHERE子句中,若是索引列是函數的一部分.優化器將不使用索引而使用全表掃描. 
舉例: 
低效: 
SELECT … FROM  DEPT  WHERE SAL * 12 > 25000; 
高效: 
SELECT … FROM DEPT WHERE SAL > 25000/12; 

1四、用>=替代> 
高效: 
SELECT * FROM  EMP  WHERE  DEPTNO >=4 
低效: 
SELECT * FROM EMP WHERE DEPTNO >3 

1五、 用UNION替換OR (適用於索引列) 
一般狀況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將形成全表掃描. 注意, 以上規則只針對多個索引列有效.
若是有column沒有被索引, 查詢效率可能會由於你沒有選擇OR而下降. 在下面的例子中, LOC_ID 和REGION上都建有索引. 
高效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 
UNION 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE REGION = 「MELBOURNE」 
低效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 OR REGION = 「MELBOURNE」 
若是你堅持要用OR, 那就須要返回記錄最少的索引列寫在最前面. 

1六、 老是使用索引的第一個列: 
若是索引是創建在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器纔會選擇使用該索引. 這也是一條簡單而重
要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引 
例:好比你建立了索引(account,age,classno)三個字段爲索引,那麼你的sql語句使用where的時候應該先使用account,此時才能使用索
引,若是你的where的第一個條件使用的是age或者classno那麼將進行全表搜索,而忽略了索引。

1七、用UNION-ALL 替換UNION ( 若是有可能的話): 
當SQL 語句須要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 而後在輸出最終結果前進行排序. 若是用UNION
ALL替代UNION, 這樣排序就不是必要了. 效率就會所以獲得提升. 須要注意的是,UNION ALL 將重複輸出兩個結果集合中相同記錄. 所以各
位仍是要從業務需求分析使用UNION ALL的可行性. UNION 將對結果集合排序,這個操做會使用到SORT_AREA_SIZE這塊內存. 對於這塊內存的
優化也是至關重要的. 下面的SQL能夠用來查詢排序的消耗量 
低效: 
SELECT  ACCT_NUM, BALANCE_AMT 
FROM  DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
UNION 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
高效: 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
UNION ALL 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 

1八、避免改變索引列的類型.
好比age字段爲int型,而後你查詢的時候寫的是 where age='13',雖然查詢出來的結果是同樣的可是效率會下降,由於數據庫內部多作了個
操做,自動對字符123 進行TO_NUMBER(‘123′) 處理

1九、 須要小心的WHERE子句: 
某些SELECT 語句中的WHERE子句不使用索引. 這裏有一些例子. 
在下面的例子裏, (1)‘!=’ 將不使用索引. 記住, 索引只能告訴你什麼存在於表中, 而不能告訴你什麼不存在於表中. (2) ‘||’是字符
鏈接函數. 就象其餘函數那樣, 停用了索引. (3) ‘+’是數學函數. 就象其餘數學函數那樣, 停用了索引. (4)相同的索引列不能互相比較,
這將會啓用全表掃描. 

20、 優化GROUP BY,儘可能使用where代替having: 
提升GROUP BY 語句的效率, 能夠經過將不須要的記錄在GROUP BY 以前過濾掉.下面兩個查詢返回相同結果但第二個明顯就快了許多. 
低效: 
SELECT JOB , AVG(SAL) 
FROM EMP 
GROUP by JOB 
HAVING JOB = ‘PRESIDENT’ 
OR JOB = ‘MANAGER’ 
高效: 
SELECT JOB , AVG(SAL) 
FROM EMP 
WHERE JOB = ‘PRESIDENT’ 
OR JOB = ‘MANAGER’ 
GROUP by JOB 

2一、不要使用SELECT *  這點不太容易作到。但是,若是在SELECT中指定你所須要的列,那將會帶來如下的好處:  1 減小內存耗費和網絡的帶寬  2 你能夠獲得更安全的設計  3 給查詢優化器機會從索引讀取全部須要的列 

相關文章
相關標籤/搜索