如何使 SQL Server高效 –T-SQL(ITPUT 討論匯總)

來源:互聯網
上載者:User

2、      您認為在T-SQL編寫(包括預存程序、函數和視圖)上,哪些因素會影響SQL Server效率?

討論匯總——索引使用

l  沒有索引或者沒有用到索引、I/O輸送量小、沒有建立計算資料行導致查詢不最佳化、鎖或者死結、查詢語句不夠最佳化等

l  對大表而言。那些不走索引的語句,錯誤scan的語句,還有那些強制使用HINT的語句,可能會因為時間的推移,影響了SQL Server對最優計劃的產生

l  避免無法使用索引的過濾條件。如 WHERE dbo.ufn.Test(ID)=1

l  確儲存在適合查詢的索引

l  根據查詢條件,建立索引,最佳化索引、最佳化訪問方式,限制結果集的資料量。注意填滿因數要適當(最好是使用預設值0)。

l  如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。 like 'a%' 使用索引 like '%a' 不使用索引用 like '%a%' 查詢時,查詢耗時和欄位值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對於欄位的值很長的建全文索引

討論匯總——遊標:

l  遊標的頻繁 "開 / 關", 既消耗資源, 同時會給相關的表加"鎖"

l  可以通過集合運算的方式去處理資料的情況下,避免使用遊標

l  預存程序通過遊標的方式,將函數的功能放在了遊標的計算中,這樣速度有了一些提高

l  考慮將遊標用其他方式改寫(需要驗證方法是否有效,無法保證效能的改寫,可能比直接使用遊標更糟糕),或確保遊標高效

l  個人補充:

a)  對於必須逐行處理的情況,建議直接使用遊標,如果要避免對構成遊標來來源資料的影響,可以考慮使用靜態資料指標。對於可以使用集合處理模式替代洲標的情況,也要考慮替代之後的查詢複雜性和涉及的資料量,如果這個修改產生的查詢非常複雜或涉及大量資料,那麼用遊標可能可以得到更佳或者更穩定的效果,建議通過測實驗證決定最終的方案

b)  注意遊標類型的選擇

c)  經常使用遊標片大量資料量,考慮適當調整cursor threshold選項(非同步產生控制)

討論匯總——暫存資料表與表變數

l  表變數和暫存資料表的使用要有規定,大小也要有個估計

l  暫存資料表和記憶體表要分別對待

l  個人補充:表變數不受事務控制,其資料寫入效率比暫存資料表高;但SQL Server不為表變數產生統計資訊,這意味著如果表變數參與查詢的話,查詢最佳化工具無法評估表變數的資料,從而導致無法有效評估查詢方案成本,所以,如果資料需要參與查詢的話,始終建議使用暫存資料表(尤其是在複雜查詢中,這個非常重要)。另外注意的一點,表變數並不確保只在記憶體中存在,當資料量大時,其資料仍然會寫入tempdb

討論匯總——綜合

l  預存程序、視圖、函數的一個好處是查詢計劃重用(預先編譯)),但還是要注意會導致重編譯的操作,例如預存程序中引用和暫存資料表、視圖結構更改等

l  使用不合適的資料類型, 如與表欄位不一致, 或發生隱式轉換 (字元轉數字)

l  SET NOCOUNT ON , 避免DML操作不必要的網路傳輸

l  最典型的函數加於欄位上再判斷。不正確的實現邏輯將導致效能問題。。當然,這本不屬於DB平台的事兒了,是實現者的事兒

l  編寫SQL語句時,在保證完成需要情況下盡量保證SQL簡單易讀,導致效率抵消的原因有:

a)  過大的事務操作導致事務之間嚴重阻塞

b)  返回過多無用資料引發磁碟和網路壓力

c)  過多的非集合化操作,如在返回列頻繁調用某個函數

d)  查詢中使用負邏輯

e)  不必要的排序,,查詢不需要的資料

f)  冗餘的判斷邏輯,,多層視圖的嵌套引用.

l  檢查不良的SQL,考慮其寫法是否還有可最佳化內容

a)  檢查子查詢。考慮SQL子查詢是否可以用簡單串連的方式進行重新書寫

b)  考慮資料庫的最佳化器

c)  盡量避免大事務操作, 提高系統並發能力

d)  盡量避免向用戶端返回大資料量, 如採用分頁

e)  盡量避免遊標使用進行大規模資料的串連和遍曆

l  資料庫引擎的本身的最佳化。每個資料庫的查詢引擎也是在不斷進化當中的,有些以前高效的語句現在顯得落伍了

l  .資料庫設計最佳化:在針對不同主題,不同分析方向的時候資料本身的設計結構也會使得SQL語句的寫法有所不同

l  70%效能問題出自不良的SQL語句。條件不符合SAR規範,遊標濫用,事務過長,複雜商務邏輯實現追求功能,不考慮效能等等

l  避免大表的distinct

l  T-SQL編寫要對複雜度進行規定,不能無限制的嵌套或者Union等等。T-SQL中檢索資料規模也需要估計

l  在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的資料,浪費了伺服器的I/O資源,加重了網路的負擔降低效能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯結訪問表,後果嚴重。

l  預存程序要設計合理,當然提示資料庫效率,主要在表的結構和使用合理的查詢方法

l  視圖的資料要放在記憶體中執行,這樣才能提升效率,但是要加記憶體

l  join的時候要命中index,少用多層嵌套,可以考慮用臨時表

l  設計SQL後,應使用explain命令檢查SQL,看是否使用到索引,是否存在filesort,重點檢查檢索的行數(rows)是否太大。一般來說.:

a)  rows<1000,是在可接受的範圍內的。

b)  ows在1000~1w之間,在密集訪問時可能導致效能問題,但如果不是太頻繁的訪問(頻率低於1分鐘一次),又難再最佳化的話,可以接受,但需要注意觀察

c)  rows大於1萬時,應謹慎考慮SQL的設計,最佳化SQL,最佳化db,一般來說不允許頻繁運行(頻率低於1小時一次)

d)  rows達到10w層級時,堅決不能做為即時啟動並執行SQL。但導資料場合除外,但導資料必須控制好時間,頻度

l  在設計SQL,尤其是稍微複雜的SQL時,一定要在測試環境甚至是實際環境上預先進行explain

l  SQL語句避免不符合SARS條件的

l  遊標和觸發器盡量避免使用

l  避免長事務,避免出現阻塞和死結 

l  複雜邏輯可以多次實現

l  動態拼接SQL語句是影響SQLServer效率的一個方面

l  預存程序中多表的串連查詢也是影響SQL Server效率的一個方面,當然是許多資料庫都具備的毛病,大概是CBO產生執行計畫不佳的一個問題,迫不得已多使用暫存資料表

l  應該採用函數或預存程序代替複雜的視圖,效能更好

個人補充:使用自訂函數的時候要注意評估。返回單個值的函數最好能夠保障是確定性函數;查詢最佳化工具不會為多語句資料表值函式建立統計資訊,所以如果多語句資料表值函式是用於關聯查詢的話,可能會產生較差的查詢方案

l  SQL Server沒有oracle的非阻塞讀,不光是寫/寫,讀/寫也會有衝突,應該勁量避免,比如:使用短小事務,合理設定並使用索引,如果可以的話做讀寫分離;影響SQL瓶頸的因素有很多,包括記憶體不足,硬體不行,或者沒有足夠的記憶體供SQL Server 使用,缺少有用的索引等,網路通訊不好,磁碟配置了,如tempdb 的配置,是否為查詢最佳化工具提供了最佳化複雜查詢的最有利條件

個人補充:讀寫衝突,可以通過控制交易隔離等級(或者相關的表提示)來控制

l  .資料的量級:在資料量低大的情況下高效率的SQL語句在資料量高的情況下就不能用了,反之亦然

個人補充:T-SQL執行包括編譯(查詢方案評估選擇)和執行兩個步驟,在查詢方案選擇的步驟,查詢最佳化工具可以根據統計資訊、對象結構評估出有效查詢方案,當然,如果查詢過於複雜,或者是查詢成本評估所需要的資訊不準確,評估的結果也會存在誤差,所以大部分情況下不會出現需要根據資料量隨時調整查詢的情況

l  T-SQL方面SQL Server缺乏Oracle完備的分析函數支援功能,也缺乏一些行列轉換、樹形目錄結構方面的函數,雖然可以通過遞迴cte、xml等函數解決

個人補充:內建函數的多少無法對比,每個資料庫都有自己的一些考慮,但常用的基本上是不缺的,對於需要但確實沒有的,可以考慮自己寫CLR函數。行列轉換有 PIVOT 和 UNPIVOT;階層有 hierarchyid 資料類型和對應的一些函數

個人補充

l  複雜查詢是需要特別注意控制的。越複雜的查詢,意味著可選擇的查詢方案越多,查詢評估所涉及的方面越廣,這意味著查詢最佳化工具評估查詢方案的成本越高,涉及的因素多,意味著評估的方案準確性越低。所以過於複雜的查詢,往意味著效能很難保障。瞭解SQL語句的處理過程,有助於理解這個問題(在線上說明中搜尋“SQL 陳述式處理”)可以得到這方面的說明。另外,要特別注意兩種複雜查詢:

a)  很多個CTE定義組成的查詢。單看每個CTE定義,都很簡單,但最終組合起來的,很可能是一個很複雜的查詢,可以通過查看執行計畫來確定。特別需要注意的是,通過CTE定義將執行步驟寫得再清晰和一目瞭然,最終執行也基本上不是按照寫的步驟去做的

b)  視圖(包括資料表值函式)嵌套導致的複雜查詢。查詢涉及的每個視圖可能很簡單,但一層層嵌套組合起來,可能最終也形成一個複雜查詢,這個也可以勇冠看執行計畫確定。(盡量避免在資料庫中使用模組化的設計思想)

l  注意實現方法的控制。比較常見的有下面這些:

a)  使用 JOIN 代替 EXISTS(包括IN)。這種很多時候容易出問題,特別是無法通過結構定義確定JOIN是否會產生一對多之類的情況下。EXISTS只需要考慮是否存在,JOIN還需要考慮資料是一對一,還是一對多或多對多,這兩者導致的查詢成本評估是不一樣的

b)  過多的 IN(值的列表)。這種基本上會被判斷為一堆的OR條件,而且會需要評估每個值,很多時候查詢成本是比較高的。可以考慮把值先放入暫存資料表,再IN 暫存資料表

c)  減少OR條件。不少的情況下,將OR條件改成多個 UNIONALL的結果會更高效一些

d)  注意條件和JOIN中的資料類型轉換。儘可能使用顯式的資料類型轉換,並將轉換的目標放在常量/變數/參數或者資料少的一方。隱式(自動)的資料類型轉換是根據類型優先順序確定轉換目標的,如果轉換操作發生在資料量大的一方,那查詢就會比較差了

  討論帖 之前的討論話題:1、 您認為在設計SQL Server對象時,主要會考慮哪些因素來避免出現效能問題?   後續討論話題:

3、 在設計資料庫操作程式上,您認為應該注意哪些事項,以確保能夠有效地使用資料庫?

4、 在您的SQL Server使用過程中,有哪些令您非常困惑的效能問題 ?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.