1. 程式人生 > >SQL:常用優化方式

SQL:常用優化方式

  在SQL查詢中為了提高SQL執行效率,我們通常會採取一些措施對查詢語句進行SQL優化。

一.常用的優化方式:

  1、儘量避免全表掃描,首先硬考慮在 where 及 order by 涉及的列上簡歷索引。
  2、應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描。
  3、應儘量避免在 where 子句中使用 != 或者 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。
  4、應儘量避免在 where 子句中使用 or 來連線條件,否則將導致引擎放棄使用索引而進行全表掃描。
  5、in 和 not in 應避免使用,在某些特定的情況下(如,使用 in ,且該列中存在null

值)會導致全表掃描,如:
  select id from t where num in (1,2,3)
  對於連續的數值,能用 between 就儘量少使用 in
  select id from t where num between 1 and 3
  6、like + 雙萬用字元% 通常也會導致全表掃描,如
  select id from t where name like '%abc%'
  7、不要在 where 子句中的 = 左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引,如:
  select id from t where num/2 = 100

  應改為:
  select id from t where num = 100 * 2
  8、應儘量避免在 where 子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描,如:
  select id from t where substr(name,1,3) = 'abc'
  應該為:
  select id from t where name like 'abc%'
  9、在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
  10、避免一些沒有意義的查詢,如需生成一個空表介面:
  select col1,col2 into #t from t where 1 = 0

  這類程式碼不會反悔任何結果集,但是會消耗系統資源的,應該為:
  create table #t(...)
  11、使用 exists 代替 in 有時(比如:B表資料量大於A表時)會是一個好的選擇
  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)
  12、並不是所有索引對查詢都有效,SQL是根據表中資料來進行查詢優化的,當索引列有大量資料重複時,SQL查詢可能不會去利用索引。
  13、索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率。在執行 insert 或 update 時有可能會對索引進行重建。
  14、儘量使用數字型欄位(int,bigint等),若只含數值資訊的欄位儘量不要涉及為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。引擎在處理查詢和連線是會逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。
  15、儘量合理設定的欄位長度,避免執行時佔用過多資源
  16、不要使用select * from t的形式進行查詢,使用具體的欄位列表代替 * , 一來避免讀取非使用的欄位列,而來防止表結構變更導致後續的錯列問題。

二.SQL通用書寫規範(基於vertica資料庫-列儲存資料庫)
1.通用規範

  1、進行 delete 、 update 操作後及時進行 commit 或 rollback 操作
  vertica鎖機制不同於關係型資料庫,在進行 delete 或 update 操作時會進行 X lock table , 所以進行上述操作後需要及時釋放鎖資源
  2、避免使用子查詢、or,將子查詢轉化為表連線方式,or 轉化為 in
  or 操作很難優化,or 可轉換為 union all 或 in 操作

2.select語句

  1、明確查詢欄位,禁止使用 select *
  避免因表結構變更導致程式異常;明確欄位,避免讀取所有欄位列
  2、避免出現隱式轉換,保持SQL中變數型別與欄位型別一直
  條件語句中資料型別以傳入引數為準。id 定義為int型,在程式中使用 id = '1',就會發生隱式轉換,將 id 轉換為varchar型別,影響資料庫效能,因此應使用id = 1
  3、where 條件所涉及的過濾欄位儘量選擇基數低的列放在前面
  過濾欄位選用高選擇性的欄位。
  4、避免對 = 左側欄位使用函式、運算,避免在 join 、group by 中使用函式,這樣可以讓優化器能更好的發揮作用
  5、避免使用not、<>、is null、is not null條件
  6、like子句儘量前置匹配,前置不加%
  “%”字首模糊匹配效率低
  7、order by 欄位順序儘量與 projection 中的 order by 順序保持一致
  projection 中已經排序過的資料
  8、多用 = 操作;>,<操作轉換為>=,<=
  “=”號操作可直接定位到相應的位置,>,<操作需要再移一位才能定位
  9、儘可能使用where條件替代having子句
  SQL語句中先執行 where 後執行 having ,過濾的結果越多,group by 的代價越小。

3.insert語句

  1、insert時建議指定欄位名,避免欄位順序變動後資料插入錯誤
  2、當需要插入大量資料時,一客使用copy方式裝載,避免執行大量 insert 語句
  3、creat table as select 時,可以使用copy_table 函式提高資料複製效率

4.update語句

  1、避免 update 語句無 where 條件

5.dalete語句

  1、避免 dalete 語句無 where 條件
  2、刪除大量資料時,使用trancate語句

6.其他注意事項

  1、使用 strcat 函式時,必須檢驗strcat函式中欄位資料型別是否為字元型,若為非字元型需強制在使用 strcat 函式前加 to_char 轉換
  當前 strcat 函式在執行欄位型別為非字元型時,若程式出錯,則SQL無法中止執行,會持續佔用系統資源,且不返回任何報錯資訊。