SQL開發規範及其優化

SQL開發規範及其優化(Oracle爲例)

1.利用PL/SQL工具進行SQL美化和格式化

  1. PL/SQL美化
    在這裏插入圖片描述

  2. 專用複製

在這裏插入圖片描述

在這裏插入圖片描述

​ 自定義模板
在這裏插入圖片描述

2.SQL規範

  1. SQL語句字符全部大寫。

    系統出問題時,最先要查詢的就是數據。要在大量的日誌中快速地定位到相關SQL是比較艱難的,SQL語句全部大寫可以幫助我們更快速的找到它們。

  2. 書寫風格美化:增加空格,增加別名,換行。

3.SQL優化

  1. 現網頻發故障點

    1. 大表關聯,導致查詢時間過長。
    2. 避免SELECT * 的使用,該問題會導致數據庫在解析的過程中將*依次轉換成所有的列名,這個工作室通過查詢數據字典完成的,會導致耗費過多時間。
      在這裏插入圖片描述
  2. 索引問題:法則:不要在建立的索引的數據列進行如下操作。

    1. 避免在索引字段進行計算操作。

    2. 避免在索引字段上使用not,<>,!=,not in,not exit,會導致查詢不走索引而執行全表掃描。

      1. 如果不等條件的值不多,而且是確認的,可以改成爲等值或IN查詢,比如status狀態字段一般值類別很少。

      2. 如果不等條件之外的值很多,可以改爲>或<的形式。

在這裏插入圖片描述

  1. 不能用包含null值得列作爲索引,任何包含null值的列都不會被包含在索引中。即使索引有多列這樣的情況,只要這些列中有一列含有null,該列就會從索引中排除。

  2. 避免在索引列上出現數據類型轉換。

在這裏插入圖片描述

  1. 避免在索引字段上使用函數也會導致不走索引。
 如:
 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'
  1. 對索引列使用OR將造成全表掃描(使用UNION)。
 // UNION 結果集中的列名總是等於 UNION 中第一個 SELECT 語句中的列名。
 SELECT column_name(s) FROM table_name1
 UNION
 SELECT column_name(s) FROM table_name2
 
 // 默認地,UNION 操作符選取不同的值。如果允許重複的值,請使用 UNION ALL。
 SELECT column_name(s) FROM table_name1
 UNION ALL
 SELECT column_name(s) FROM table_name2
 
 UNION ALL 命令和 UNION 命令幾乎是等效的,不過 UNION ALL 命令會列出所有的值。
 因爲 UNION ALL 僅僅是簡單的合併查詢結果, 並不會做去重操作, 也不會排序, 所以 UNION ALL 效率要比 UNION.
 所以在能夠確定沒有重複記錄的情況下, 儘量使用 UNION ALL
  1. 左模糊查詢也將導致全表掃描: select id from t where name like ‘%abc%’ 。若要提高效率,可以考慮全文檢索。

  2. 如果在 where 子句中使用參數,也會導致全表掃描。因爲SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作爲索引選擇的輸入項。如下面語句將進行全表掃描: select id from t where num=@num 可以改爲強制查詢使用索引: select id from t with(index(索引名)) where num=@num

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

如: select id from t where num/2=100 應改爲: select id from t where num=100*2
  1. like通配符可能導致索引失效。

  2. 聯合索引,查詢時的條件列不是聯合索引中的第一個列,索引失效。

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

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

  5. SQL的排序對性能成本的消耗是非常大的,如果可以請把排序放在程序中來實現。

  6. 當數據量非常大的時候,一定要考慮分頁查詢,衆多上線升級中由於沒分頁把內存庫搞掛的案例比比皆是。

  7. 有ORDER BY 和 ROWNUM時,先給ROWNUM賦值,然後再對結果ORDER BY

4.執行計劃

在這裏插入圖片描述

​ 我們首先看第一列的Description,下面的內容分別是我們這條SQL的執行步驟,縮進量最多的步驟最先執行,如果縮進量相同,則按照從上往下執行。

TABLE ACCESS FULL:全表掃描

INDEX UNIQUE SCAN:唯一索引範圍內查找

TABLE ACCESS BY INDEX ROWID:根據索引找到的ROWID來查找需要的數據

分析步驟:

  1. 查看總COST,獲得資源耗費的總體印象
  2. 按照從左往右,從上至下的方法,瞭解執行計劃的執行步驟
  3. 分析表的訪問方式
  4. 分析表的連接方式和連接順序

總結:這裏看到的執行計劃,只是SQL運行前可能的執行計劃,實際運行時可能因爲軟硬件環境的不同,而有所改變,而且cost高的執行 計劃,不一定在實際運行起來,速度就一定差,我們平時需要結合執行計劃,和實際測試的運行時間,來確定一個執行計劃的好壞。

5.其他

  1. 請使用事務,特別是當查詢比較耗時。如果系統出現問題,這樣做會救你一命的。一般有些經驗的程序員都有體會–你經常會碰到一些 不可預料的情況會導致內存崩潰。

    同時,只要有可能,在程序中儘量多使用COMMIT,這樣程序的性能得到提高需求也會因爲COMMIT 所釋放的資源而減少。

  2. 在程序編碼時使用大數據量的數據庫
    程序員在開發中使用的測試數據庫一般數據量都不大,可經常的是最終用戶的數據量都很大。

  3. 多層子查詢嵌套
    可以考慮適當拆成幾步,先生成一些臨時數據表,再進行關聯操作

求也會因爲COMMIT 所釋放的資源而減少。

  1. 在程序編碼時使用大數據量的數據庫
    程序員在開發中使用的測試數據庫一般數據量都不大,可經常的是最終用戶的數據量都很大。

  2. 多層子查詢嵌套
    可以考慮適當拆成幾步,先生成一些臨時數據表,再進行關聯操作

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