sql優化原則與技巧

加快sql查詢是很是重要的技巧,簡單來講加快sql查詢的方式有如下幾種:
1、索引的引用html

一、索引通常能夠加速數據的檢索速度,加速表與表之間的連接,提升性能,因此在對海量數據進行處理時,考慮到信息量比較大,應該對錶創建索引,包括在主鍵上創建聚簇索引,將聚合索引創建在日期刊上等。索引的優勢有不少,可是對於索引的創建,還須要考慮實際狀況,而不是對每個列創建一個索引,好比針對大表的分組、排序等字段,都要創建相應索引,同時還應該考慮創建符合索引。增長索引的同時也有不少很差的方面,首先,建立索引和維護索引都耗費時間,且隨着數據量的增長而增長;其次,索引佔據物理空間,聚簇索引的空間更大。最後,當對錶進行增長、刪除和修改的時候,索引也要動態的維護。因此索引的引用有如下幾個原則:java

(1)當插入數據爲表中數據的百分之10以上時,首先須要刪除該表的索引來提升數據的插入效率,而後再從新創建索引;sql

(2)避免在索引列上使用函數或計算,在where字句中,若是索引是函數的一部分,優化器將再也不使用索引,將使用全表掃描;例如:數據庫

select * from table where hh*10>1000;//低效
select * from table where hh>1000/10;//更高效

(3)儘可能避免在索引列上使用not,!=和<>,索引只能告訴什麼在表中,而不能告訴什麼不在表中,當數據庫趕上以上幾種符號時,將再也不使用索引,使用全表掃描oracle

(4)檢索中不要對索引進行處理,如TRIM,TO_DATE,類型轉換等,這會破壞索引函數

(5)避免在索引列上使用IS NULL 或 IS NOT NULL。避免在索引列上使用任何能夠爲空的列,這樣將沒法使用此索引。由於空值不存在於索引列中,因此當where字句中對索引進行空值比較,將沒法使用該索引。性能

(6)在索引列上,使用>=代替>,好比:優化

select * from table where hh>10;//低效
select * from table where hh>=10.0000001//相對高效

2、SQL語句的優化spa

介紹幾種SQL語句的優化技巧:3d

(1)where字句中的連接順序

oracle採用自下而上的順序解析where字句,因此表之間的連接必須寫在其餘where條件以前,那些能夠濾過大量紀錄的條件必須寫在where字句的末尾,例如:

select * from table e
      where h>500     
                  and d='001'
                  and 25<(select count(*) 
                               from table 
                               where count=e.count);  //低效

select * from table e
      where  25<(select count(*) 
                          from table 
                          where count=e.count);    
                   and  h>500
                   and d='001';//更高效     

(2)刪除全表時,用truncate而不用delete。由於truncate是ddl不是dml(truncate只能在刪除全表時使用),例如:

Truncate table account;
比
delete from account;
快1000倍

(3)儘可能多使用commit,只要有可能就對程序中每一個delete,insert,update使用commit,這樣系統會由於commit所釋放的資源而大大提升效率。

(4)用exists代替in,能夠提升查詢的效率。例如:

SELECT * FROM ACCOUNT
    WHERE AC_CODE 
    NOT IN (
              SELECT CODE
              FROM GOODS
              WHERE NUM='001')       //低效

SELECT * FROM ACCOUNT
    WHERE NOT EXISTSSELECT CODE
          FROM GOODS
          WHERE CODE=ACCOUNT.AC_CODE
           AND NUM='001')             //更高效

(5)使用group by

能夠將不須要的語句在group by以前過濾掉

(6)避免使用HAVING字句

HAVING字句只有在檢索出全部記錄以後,纔會對結果集進行過濾,這樣涉及到排序,統計等操做,若是能經過WHERE字句限制記錄的數目,就能夠減小開銷。用Where子句替換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進行過濾。因而可知,要想過濾條件起到正確的做用,首先要明白這個條件應該在何時起做用,而後再決定放在那裏 。

(7)有條件的使用union-all代替union提升效率

(8)在全部查詢的SQL語句中要特別注意減小對錶的查詢,如:

(9)select字句中避免使用*

當想在select字句中列出全部的列時,使用*是一個很方便,可是很低效的方法,由於在oracle中,會經過查詢數據字典,將*依次轉換爲全部的列名,很耗時

(10)Order by語句

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

(11)帶通配符(%)的like語句

目前的需求是這樣的,要求在職工表中查詢名字中包含cliton的人。能夠採用以下的查詢SQL語句:

    select * from employee where last_name like '%cliton%';

這裏因爲通配符(%)在搜尋詞首出現,因此Oracle系統不使用last_name的索引。在不少狀況下可能沒法避免這種狀況,可是必定要心中有底,通配符如此使用會下降查詢速度。然而當通配符出如今字符串其餘位置時,優化器就能利用索引。在下面的查詢中索引獲得了使用:

    select * from employee where last_name like 'c%';

(12)選擇最有效率的表名順序(只在基於規則的優化器中有效)

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

(13) 整合簡單,無關聯的數據庫訪問: 
若是你有幾個簡單的數據庫查詢語句,你能夠把它們整合到一個查詢中(即便它們之間沒有關係) 

(14)刪除重複記錄: 
最高效的刪除重複記錄方法 ( 由於使用了ROWID)例子: 
DELETE  FROM  EMP E  WHERE  E.ROWID > (SELECT MIN(X.ROWID) 
FROM  EMP X  WHERE  X.EMP_NO = E.EMP_NO); 

(15)使用表的別名(Alias)

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

(16)sql語句用大寫的;由於oracle老是先解析sql語句,把小寫的字母轉換成大寫的再執行 
(17) 在java代碼中儘可能少用鏈接符「+」鏈接字符串! 

(18) 老是使用索引的第一個列: 
若是索引是創建在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器纔會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引 

3、函數的使用技巧

雖然有時肆意的使用函數,會將性能下降,可是用好函數有時也能提升性能和可讀性。如:

 

其餘的一些方法能夠參考http://www.cnblogs.com/ziyiFly/archive/2008/12/24/1361380.html

相關文章
相關標籤/搜索