天天看點

SQL Server資料庫性能優化技巧

查詢速度慢的原因很多,常見如下幾種:

1、沒有索引或者沒有用到索引;

2、I/O吞吐量小,形成了瓶頸效應;

3、記憶體不足;

4、網絡速度慢;

5、查詢出的資料量過大;

6、鎖或者死鎖;

7、傳回了不必要的行和列;

8、查詢語句不好,沒有優化。

可以通過如下方法來優化查詢:

硬體/網絡方面

1、更新硬體。

2、提高網速。

3、擴大伺服器的記憶體。

4、增加伺服器CPU個數。

5、把資料、日志、索引放到不同的I/O裝置上。

6、DB Server和APP Server分離。

7、應用分布式分區視圖。

索引方面

8、根據查詢條件建立索引,優化索引。

9、索引應該盡量小,使用位元組數小的列建索引好。

10、不要對有限的幾個值的字段建單一索引(如性别字段)。

11、對于查詢字段的值很長的建全文索引。

12、要注意索引的維護,周期性重建索引,重新編譯存儲過程。

13、 如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示聲明指定索引。

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

15、 在使用索引字段作為條件時,如果該索引是聯合索引,那麼必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引将不會被使用。

16、 如果臨時表的資料量較大,需要建立索引,那麼應該将建立臨時表和建立索引的過程放在單獨一個子存儲過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。

17、 如果某列存在空值,即使對該列建索引也不會提高性能。

SQL語句方面

18、如果是使用LIKE進行查詢的話,簡單的使用索引是不行的,LIKE 'a%' 使用索引,LIKE '%a' 不使用索引,用 LIKE '%a%' 查詢時,查詢耗時和字段值總長度成正比,是以不能用CHAR類型,而是VARCHAR。

19、查詢時不要傳回不需要的行、列。

20、一定要将函數和列名分開。如果必須用函數的時候,建立計算列再建立索引來替代。

21、NOT IN會多次掃描表,使用EXISTS、NOT EXISTS,IN,LEFT OUTER JOIN來替代,特别是左連接配接,而EXISTS比IN更快,最慢的是NOT操作。

22、BETWEEN在某些時候比IN速度更快,BETWEEN能夠更快地根據索引找到範圍。

23、用OR的子句可以分解成多個查詢,并且通過UNION連接配接多個查詢。它們的速度隻同是否使用索引有關。多個OR的子句沒有用到索引,改寫成UNION的形式再試圖與索引比對。

24、在IN後面值的清單中,将出現最頻繁的值放在最前面,出現得最少的放在最後面,減少判斷的次數。

25、一般在GROUP BY、HAVING子句之前就能剔除多餘的行,是以盡量不要用它們來做剔除行的工作。它們的執行順序應該如下最優:WHERE子句選擇所有合适的行,GROUP BY用來分組統計行,HAVING子句用來剔除多餘的分組。這樣GROUP BY、HAVING的開銷小,查詢快。對于大的資料行進行GROUP BY和HAVING十分消耗資源。如果GROUP BY的目的不包括計算,隻是分組,那麼用DISTINCT更快。

26、盡量使用批處理。

27、不要在一句話裡再三的使用相同的函數,浪費資源,将結果放在變量裡再調用更快。

28、分析select emp_name form employee where salary > 3000 在此語句中若salary是FLOAT類型的,則優化器對其進行優化為CONVERT(float,3000),因為3000是個整數,我們應在程式設計時使用3000.0而不要等運作時讓DBMS進行轉化。對其它類型也是一樣。

29、注意WHERE子句寫法,必須考慮語句順序,應該根據索引順序、範圍大小來确定條件子句的前後順序,盡可能的讓字段順序與索引順序相一緻,範圍從大到小。

30、盡量使用EXISTS代替SELECT COUNT(1)來判斷是否存在記錄,COUNT函數隻有在統計表中所有行數時使用,而COUNT (1)比COUNT (*)更有效率。

31、盡量使用“>=”,不要使用“>”。

32、注意表之間連接配接的資料類型,避免不同類型資料之間的連接配接。

33、盡量避免使用DISTINCT、ORDER BY、GROUP BY、HAVING、JOIN、CUMPUTE。

34、在海量查詢時盡量少用格式轉換。

35、任何對列的操作都将導緻表掃描,它包括資料庫函數、計算表達式等等,查詢時要盡可能将操作移至等号右邊。

其它方面

36、縱向、橫向分割表,減少表的尺寸。

37、設定自動收縮日志。

38、周期性清理日志。

39、對于大的資料庫不要設定資料庫自動增長,它會降低伺服器的性能。

40、避免表掃描。

41、盡可能不使用遊标。

42、用Profiler來跟蹤查詢,得到查詢所需的時間,找出SQL的問題所在。用索引優化器優化索引。

43、使用Query Analyzer,檢視SQL語句的查詢計劃和評估分析是否是優化的SQL。

44、将計算的結果預先計算好放在表中,查詢的時候再SELECT。

45、如果要插入大的二進制值到IMAGE列,使用存儲過程,千萬不要用應用程式内嵌INSERT來插入。因為應用程式首先将二進制值轉換成字元串(尺寸是它的兩倍),伺服器收到字元後又将他轉換成二進制值。存儲過程就沒有這些動作。

46、盡量少用視圖,它的效率低。對視圖操作比直接對表操作慢。

47、盡量将資料的處理工作放在資料庫上,減少網絡的開銷,如使用存儲過程。存儲過程是編譯好、優化過、并且被組織到一個執行規劃裡、且存儲在資料庫中的SQL語句,是控制流語言的集合,速度當然快。

48、函數的傳回值不要太大,這樣的開銷很大。使用者自定義函數像遊标一樣執行的消耗大量的資源,如果傳回大的結果采用存儲過程。

49、盡量避免反複通路同一張或幾張表,尤其是資料量較大的表,可以考慮先根據條件提取資料到臨時表中,然後再做連接配接。

50、要盡量避免在遊标循環中再進行表連接配接的操作。

51、如果使用到了臨時表,在存儲過程的最後務必将所有的臨時表顯式删除,先TRUNCATE TABLE,然後DROP TABLE,這樣可以避免系統表的較長時間鎖定。

52、 在某些必須使用遊标的場合,可考慮将符合條件的資料行轉入臨時表中,再對臨時表定義遊标進行操作,這樣可使性能得到明顯提高。

      經驗顯示,SQL Server 性能的最大改進得益于邏輯的資料庫設計、索引設計和查詢設計方面。反過來說,最大的性能問題常常是由其中這些相同方面中的不足引起的。其實 SQL 優化的實質就是在結果正确的前提下,用優化器可以識别的語句,充份利用索引,減少表掃描的 I/O 次數,盡量避免表搜尋的發生。