一、 任何地方都不要使用 select * from t ,用具體的字段列表代替「*」,不要返回用不到的任何字段。按需查詢。sql
ORACLE在解析的過程當中, 會將’*’ 依次轉換成全部的列名, 這個工做是經過查詢數據字典完成的, 這意味着將耗費更多的時間 。數據庫
Q:一個sql屢次利用,能夠省代碼量啊,這矛盾了...編程
二、 避免使用不兼容的數據類型oracle
select emp_name form employee where salary > 3000;
在此語句中若salary是Float類型的,則優化器很難對其進行優化,由於3000是個整數,咱們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。函數
三、適當利用索引,where、order by、group by、表關聯涉及的字段。可儘可能避免全表掃描。測試
在使用索引時必定要按索引對應字段的順序進行引用優化
放棄使用索引而進行全表掃描的狀況:orm
1)where子句中對字段進行null值判斷,如:排序
select id from t where num is null;索引
能夠在num上設置默認值0,確保表中num列沒有null值,而後這樣查詢:
select id from t where num = 0;
--- 儘可能避免數據庫存null,例如可設默認值0。
2)where子句中使用!=或<>操做符
3)or,用union或in代替or
如:
select id from t where num = 10 or num = 20;改成
select id from t where num = 10
union
select id from t where num = 20;
4)用union all代替 union
當SQL 語句須要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 而後在輸出最終結果前進行排序. 若是用UNION ALL替代UNION, 這樣排序就不是必要了. 效率就會所以獲得提升. 須要注意的是,UNION ALL 將重複輸出兩個結果集合中相同記錄. 所以各位仍是要從業務需求分析使用UNION ALL的可行性. UNION 將對結果集合排序,這個操做會使用到SORT_AREA_SIZE這塊內存. 對於這塊內存的優化也是至關重要的
5)in 和 not in,如:
Select id from t where num in (1, 2, 3);改成
Select id from t where num between 1 and 3;
對於連續數值,能用between就不要用in。
用exists替代in,not exists替代not in,由於exists引入的子查詢只是測試是否存在符號子查詢中指定條件的行,效率較高。Not in效率最低。
select num from a where num in(select num from b) ;
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num);
6)like ‘%abc%’,儘可能不要左邊也用%,或者a%c
7)where字句中對字段進行函數操做,where子句中「=」左邊進行函數/算術運算等,如:
select id from t where num/2 = 100;
select id from t where substring(name,1,3)='abc'; --name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0; --'2005-12-1'生成的id
應改成:
select id from t where num = 100*2;
select id from t where name like 'abc%' ;
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1';
8)使用日期值做爲索引,而爲了實現比較操做,可能須要將這個日期值轉換爲字符串,這樣將致使在查詢過程當中沒法用到這個日期索引值。
9)ORDER BY 子句只在兩種嚴格的條件下使用索引.
ORDER BY中全部的列必須包含在相同的索引中並保持在索引中的排列順序.
ORDER BY中全部的列必須定義爲非空
四、選擇最有效率的表名順序(只在基於規則的優化器中有效)
ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最早處理,在FROM子句中包含多個表的狀況下,你必須選擇記錄條數最少的表做爲基礎表。若是有3個以上的錶鏈接查詢, 那就須要選擇交叉表(intersection table)做爲基礎表, 交叉表是指那個被其餘表所引用的表。
五、WHERE子句中的鏈接順序
ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的鏈接必須寫在其餘WHERE條件以前, 那些能夠過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。
六、用Where子句替換HAVING子句,將不須要的記錄在GROUP BY 以前過濾掉
避免使用HAVING子句, HAVING 只會在檢索出全部記錄以後纔對結果集進行過濾。這個處理須要排序,總計等操做. 若是能經過WHERE子句限制記錄的數目,那就能減小這方面的開銷. (非oracle中)on、where、having這三個均可以加條件的子句中,on是最早執行,where次之,having最後,由於on是先把不 符合條件的記錄過濾後才進行統計,它就能夠減小中間運算要處理的數據,按理說應該速度是最快的,where也應該比having快點的,由於它過濾數據後 才進行sum,在兩個表聯接時才用on的,因此在一個表的時候,就剩下where跟having比較了。在這單表查詢統計的狀況下,若是要過濾的條件沒有涉及到要計算字段,那它們的結果是同樣的,只是where可使用rushmore技術,而having就不能,在速度上後者要慢若是要涉及到計算的字 段,就表示在沒計算以前,這個字段的值是不肯定的,根據上篇寫的工做流程,where的做用時間是在計算以前就完成的,而having就是在計算後才起做 用的,因此在這種狀況下,二者的結果會不一樣。在多表聯接查詢時,on比where更早起做用。系統首先根據各個表之間的聯接條件,把多個表合成一個臨時表 後,再由where進行過濾,而後再計算,計算完後再由having進行過濾。因而可知,要想過濾條件起到正確的做用,首先要明白這個條件應該在何時起做用,而後再決定放在那裏
七、使用表的別名(Alias)
當在SQL語句中鏈接多個表時, 請使用表的別名並把別名前綴於每一個Column上.這樣一來,就能夠減小解析的時間並減小那些由Column歧義引發的語法錯誤。
八、用EXISTS替換DISTINCT
當提交一個包含一對多表信息(好比部門表和僱員表)的查詢時,避免在SELECT子句中使用DISTINCT. 通常能夠考慮用EXIST替換, EXISTS 使查詢更爲迅速,由於RDBMS核心模塊將在子查詢的條件一旦知足後,馬上返回結果。
九、sql語句用大寫的
由於oracle老是先解析sql語句,把小寫的字母轉換成大寫的再執行 。
十、用>=替代>
高效: SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3 二者的區別在於, 前者DBMS將直接跳到第一個DEPT等於4的記錄然後者將首先定位到DEPTNO=3的記錄而且向前掃描到第一個DEPT大於3的記錄。