1. 程式人生 > >SQL通用優化方案(where優化、索引優化、分頁優化、事務優化、臨時表優化)

SQL通用優化方案(where優化、索引優化、分頁優化、事務優化、臨時表優化)

truncate height 能夠 時有 大數據量 2017年 固然 分頁 索引優化

SQL通用優化方案:
1. 使用參數化查詢:防止SQL註入,預編譯SQL命令提高效率
2. 去掉不必要的查詢和搜索字段:其實在項目的實際應用中,很多查詢條件是可有可無的,能從源頭上避免的多余功能盡量砍掉,這是最簡單粗暴的解決方案。
3. 選擇最有效率的表名順序: 數據庫的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表放在最後,如果有3個以上的表連接查詢,那就需要選擇那個被其他表所引用的表放在最後。
4. 不要使用select *:不要使用select *,以提高查詢效率,減少輸出的數據量,提高傳輸速度(數據庫或在解析過程中將"*"依次轉換成所有列名,這意味著消耗更多的時間)
5. 盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
6. 減少訪問數據庫的次數:通過存儲過程等,把多條語句放在一個存儲過程中執行,減少數據庫訪問次數
7. 整合簡單的、無關聯的數據庫訪問:如果你有幾個簡單的數據庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系))
8. 刪除重復記錄:刪除重復記錄,減少數據庫文件大小
9. 使用表的別名(Alias):當在SQL語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤.
10. 使用列的別名:當列的名稱很長的時候,使用簡短的列的別名可以查詢結果更清晰,更簡潔。
11. 用EXISTS替代IN、用NOT EXISTS替代NOT IN:無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
12. 統計相關的查詢,影響結果集往往巨大,應避免在業務高峰期執行統計相關的查詢,或者僅在從庫中執行統計查詢。同時建議把數據先保存在內存、緩存中(如redis),再按一定策略寫入數據庫。
13. select count(*) from table;這樣不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的,可以用其他方法代替。
14. 使用truncate代替delete清空整個數據表:當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存放可以被恢復的信息. (可以恢復到執行刪除命令之前的狀態) 而當運用TRUNCATE時, 回滾段不再存放任何可被恢復的信息.當命令運行後,數據不能被恢復.因此很少的資源被調用,執行時間也會很短.

字段類型優化:
1. 盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連 接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。
2. 最好不要給數據庫留NULL,盡可能的使用 NOT NULL填充數據庫.(備註、描述、評論之類的可以設置為 NULL)

where條件語句優化:
1. WHERE子句中的連接順序:數據庫采用自右而左的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前(左), 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾(右).
2. 避免在where語句中出現字段的類型轉換(字段的類型和傳入的參數類型不一致的時候發生的隱式類型轉換)
3. 不要在where條件語句中的"="左邊進行函數、算數運算或其他表達式運算,可以通過使用冗余字段來替代函數運算,否則系統無法正確使用索引
4. where 子句中對字段進行 null 值判斷、包含not、!=、<>等操作符,或like的關鍵詞前加%(like ‘%關鍵詞‘),都無法使用索引,從而引發全表掃描.
5. 使用like進行模糊查詢時應註意,除非必要,否則不要在關鍵詞前加%,否則必然導致全表查詢

索引優化:
1. 索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
2. 用索引提高效率:合理使用索引和復合索引同樣能提高效率.但使用索引是有代價的, 索引需要空間來存儲,也需要定期維護, 每當有記錄在表中增減或索引列被修改時, 索引本身也會被修改. 這意味著每條記錄的INSERT , DELETE , UPDATE將為此多付出4 , 5 次的磁盤I/O . 因為索引需要額外的存儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢.。定期的重構索引是有必要的。
3. 在使用索引字段作為條件時,如果該索引是聯合索引,那麽必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
4. 要註意索引的維護,周期性重建索引,重新編譯存儲過程。

分頁語句優化:
1. 分頁查詢的優化。頁數比較多的情況下,如limit 10000,10 影響的結果集是10010行,查詢速度會比較慢。推薦的解決方案是:先只查詢主鍵select id from table where .. order by .. limit 10000,10(搜索條件和排序請建立索引),再通過主鍵去獲取數據。
2. 對於多張大數據量(這裏幾百條就算大了)的表JOIN,要先分頁再JOIN,否則邏輯讀會很高,性能很差。

事務的優化:
1. 盡量使用COMMIT:盡可能在程序中使用commit,這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少,commit每個數據庫引擎都不同,sqlserver默認一條sql語句就是一個事務。
2. 盡量避免大事務操作,提高系統並發能力。
3. 只在必要的情況下才使用begin tran:begin tran保證了數據的一致性,可以確保要麽幾個表都修改成功,要麽都不成功,但Begin tran付出的代價是在提交之前,所有SQL語句鎖住的資源都不能釋放,直到commit掉。Begin tran使用的原則是,在保證數據一致性的前提下,begin tran 套住的SQL語句越少越好!有些情況下可以采用觸發器同步數據,不一定要用begin tran。

臨時表優化:
1. 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
2. 使用“臨時表”暫存中間結果:將臨時結果暫存在臨時表,後面的查詢就在tempdb中了,這可以避免程序中多次掃描主表,也大大減少了程序執行中“共享鎖”阻塞“更新鎖”,減少了阻塞,提高了並發性能。同時也能簡化sql語句的復雜度。
3. 在新建臨時表時,如果一次性插入數據量很大,那麽可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然後insert。
4. 如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
5. 如果臨時表的數據量較大,需要建立索引,那麽應該將創建臨時表和建立索引的過程放在單獨一個子存儲過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。
6. 盡量避免使用distinct、order by、group by、having、join、cumpute,因為這些語句會加重tempdb的負擔。
7. 慎用大的臨時表與其他大表的連接查詢和修改,減低系統表負擔,因為這種操作會在一條語句中多次使用tempdb的系統表。

遊標優化:
1. 盡量避免使用遊標,因為遊標的效率較差,如果遊標操作的數據超過1萬行,那麽就應該考慮改寫。
2. 使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
3. 與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。

參考文章:
http://www.cnblogs.com/hellohell/p/6208466.html
http://www.cnblogs.com/520sophia/archive/2011/08/23/2150990.html
http://www.cnblogs.com/ATree/archive/2011/02/13/sql_optimize_1.html
http://database.51cto.com/art/201407/445934.htm
http://www.cnblogs.com/petitprince/archive/2010/11/23/1885994.html

版權聲明:本文采用署名-非商業性使用-相同方式共享(CC BY-NC-SA 3.0 CN)國際許可協議進行許可,轉載請註明作者及出處。
本文標題:SQL通用優化方案(where優化、索引優化、分頁優化、事務優化、臨時表優化)
本文鏈接:http://www.cnblogs.com/sochishun/p/7003513.html
本文作者:SoChishun (郵箱:14507247#qq.com | 博客:http://www.cnblogs.com/sochishun/)
發表日期:2017年6月13日

SQL通用優化方案(where優化、索引優化、分頁優化、事務優化、臨時表優化)