SQL優化常用的幾種方法

一、背景

      在使用JPA時常常出現業務複雜不方便使用名稱解析的情況,這時可採用原生SQL來實現,SQL在請求併發數量較多時效率會影響系統的整體效率,在此記錄一下sql優化的常用幾種方法。

二、優化方法

      1、對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

      2、應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。

      3、應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:

            select id from t where num is null

            可以在num列設置默認值0,然後通過=等號查詢:

            select id from t where num=0

     4、應儘量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:

            select id from t where num=10 or num=20

            此查詢可優化爲:select id from t where num=10
                                         union all
                                         select id from t where num=20

     5、下面的查詢也將導致全表掃描:
            select id from t where name like '%abc%'

            若要提高效率,可以考慮全文檢索。

     6、in 和 not in 也要慎用,否則會導致全表掃描,如:

           select id from t where num in(1,2,3)

           若查詢的數值爲連續值,則可以優化爲between來查詢:

           select id from t where num between 1 and 3

     7、如果在 where 子句中使用參數,也會導致全表掃描。因爲SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問              計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無            法作爲索引選擇的輸入項。如下面語句將進行全表掃描:

          select id from t where num=@num
           可以改爲強制查詢使用索引:
          select id from t with(index(索引名)) where num=@num

     8、應儘量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:

           select id from t where num/2=100
             應改爲:
           select id from t where num=100*2

     9、應儘量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:

           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-11-30'生成的id

           應改爲:
           select id from t where name like 'abc%'
           select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

    10、不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

    11、在使用索引字段作爲條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作爲條件時才能保證系統               使用該索引,否則該索引將不會被使用,並且應儘可能的讓字段順序與索引順序相一致。

    12、不要寫一些沒有意義的查詢,如需要生成一個空表結構:
            select col1,col2 into #t from t where 1=0
            這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
            create table #t(...)

   13、很多時候用 exists 代替 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)

   14、並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會            去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。

   15、索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因爲 insert 或             update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太             多則應考慮一些不常使用到的列上建的索引是否有必要。

   16、應儘可能的避免更新 clustered 索引數據列,因爲 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值               改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要             考慮是否應將該索引建爲 clustered 索引。

   17、應儘可能的避免更新 clustered 索引數據列,因爲 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值               改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要             考慮是否應將該索引建爲 clustered 索引。

   18、儘可能的使用char/nchar 代替 varchar/nvarchar ,因爲首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來                說,在一個相對較小的字段內搜索效率顯然要高些。

   19、任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

   20、儘量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。

   21、避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章