MS SQL Server查詢優化方法

keeking發表於2012-05-31
1. 如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。   like   'a%'   使用索引   like   '%a'   不使用索引用   like   '%a%'   查詢時,查詢耗時和欄位值總長度成正比,所以不能用CHAR型別,而是VARCHAR。對於欄位的值很長的建全文索引。
2. 在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的資料,浪費了伺服器的I/O資源,加重了網路的負擔降低效能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯接訪問表,後果嚴重。
3. 儘可能不使用游標,它佔用大量的資源。如果需要row-by-row地執行,儘量採用非游標技術,如:在客戶端迴圈,用臨時表,Table變數,用子查詢,用Case語句等等。
4. 注意UNion和UNion   all   的區別。UNION   all效能要好。
5. 注意使用DISTINCT,在沒有必要時不要用,它同UNION一樣會使查詢變慢。重複的記錄在查詢裡是沒有問題的。
6. 查詢時不要返回不需要的行、列。
7. 用select   top   100   /   10   Percent   來限制使用者返回的行數或者SET   ROWCOUNT來限制操作的行。
8. 在SQL2000以前,一般不要用如下的字句:   "IS   NULL",   " <> ",   "!=",   "!> ",   "! ”等還是不能優化,用不到索引。
9. 如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引:   SELECT   *   FROM   PersonMember   (INDEX   =   IX_Title)   WHERE   processid   IN   (‘男’,‘女’)
10. 將需要查詢的結果預先計算好放在表中,查詢的時候再SELECT。這在SQL7.0以前是最重要的手段。
11. Between在某些時候比IN速度更快,Between能夠更快地根據索引找到範圍。用查詢優化器可見到差別。   select   *   from   chineseresume   where   title   in   ('男','女')   Select   *   from   chineseresume   where   between   '男'   and   '女'   是一樣的。由於in會在比較多次,所以有時會慢些。
12. 在必要是對全域性或者區域性臨時表建立索引,有時能夠提高速度,但不是一定會這樣,因為索引也耗費大量的資源。他的建立同是實際表一樣。
13. 用OR的字句可以分解成多個查詢,並且通過UNION   連線多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到聯合索引,用UNION   all執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。
14. 儘量少用檢視,它的效率低。對檢視操作比直接對錶操作慢,可以用stored   procedure來代替她。特別的是不要用檢視巢狀,巢狀檢視增加了尋找原始資料的難度。我們看檢視的本質:它是存放在伺服器上的被優化好了的已經產生了查詢規劃的SQL。對單個表檢索資料時,不要使用指向多個表的檢視,直接從表檢索或者僅僅包含這個表的檢視上讀,否則增加了不必要的開銷,查詢受到干擾.為了加快檢視的查詢,MsSQL增加了檢視索引的功能。
15. 沒有必要時不要用DISTINCT和ORDER   BY,這些動作可以改在客戶端執行。它們增加了額外的開銷。這同UNION   和UNION   ALL一樣的道理。
16. 在IN後面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最後面,減少判斷的次數
17. 當用SELECT   INTO時,它會鎖住系統表(sysobjects,sysindexes等等),阻塞其他的連線的存取。建立臨時表時用顯示申明語句,而不是 select   INTO.   drop   table   t_lxh   begin   tran   select   *   into   t_lxh   from   chineseresume   where   name   =   'XYZ'   --commit   在另一個連線中SELECT   *   from   sysobjects可以看到   SELECT   INTO   會鎖住系統表,Create   table   也會鎖系統表(不管是臨時表還是系統表)。所以千萬不要在事物內使用它!!!這樣的話如果是經常要用的臨時表請使用實表,或者臨時表變數。
18. 一般在GROUP   BY   個HAVING字句之前就能剔除多餘的行,所以儘量不要用它們來做剔除行的工作。他們的執行順序應該如下最優:select   的Where字句選擇所有合適的行,Group   By用來分組個統計行,Having字句用來剔除多餘的分組。這樣Group   By   個Having的開銷小,查詢快.對於大的資料行進行分組和Having十分消耗資源。如果Group   BY的目的不包括計算,只是分組,那麼用Distinct更快
19. 一次更新多條記錄比分多次更新每次一條快,就是說批處理好
20. 少用臨時表,儘量用結果集和Table類性的變數來代替它,Table   型別的變數比臨時表好
21. 儘量將資料的處理工作放在伺服器上,減少網路的開銷,如使用儲存過程。儲存過程是編譯好、優化過、並且被組織到一個執行規劃裡、且儲存在資料庫中的 SQL語句,是控制流語言的集合,速度當然快。反覆執行的動態SQL,可以使用臨時儲存過程,該過程(臨時表)被放在Tempdb中。以前由於SQL   SERVER對複雜的數學計算不支援,所以不得不將這個工作放在其他的層上而增加網路的開銷。SQL2000支援UDFs,現在支援複雜的數學計算,函式的返回值不要太大,這樣的開銷很大。使用者自定義函式象游標一樣執行的消耗大量的資源,如果返回大的結果採用儲存過程
22. 不要在一句話裡再三的使用相同的函式,浪費資源,將結果放在變數裡再呼叫更快
23. SELECT   COUNT(*)的效率教低,儘量變通他的寫法,而EXISTS快.同時請注意區別:   select   count(Field   of   null)   from   Table   和   select   count(Field   of   NOT   null)   from   Table   的返回值是不同的。
24. 分析select   emp_name   form.   employee   where   salary   >   3000   在此語句中若salary是Float型別的,則優化器對其進行優化為Convert(float,3000),因為3000是個整數,我們應在程式設計時使用3000.0而不要等執行時讓DBMS進行轉化。同樣字元和整型資料的轉換。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7899089/viewspace-731581/,如需轉載,請註明出處,否則將追究法律責任。

相關文章