SQLServer性能優化之 nolock,大幅提高數據庫查詢性能

原文: SQLServer性能優化之 nolock,大幅提高數據庫查詢性能

  公司數據庫隨着時間的增加,數據愈來愈多,查詢速度也愈來愈慢。進數據庫看了一下,幾十萬調的數據,查詢起來確實很費時間。html

  要提高SQL的查詢效能,通常來講你們會以創建索引(index)爲第一考慮。其實除了index的創建以外,當咱們在下SQL Command時,在語法中加一段WITH (NOLOCK)能夠改善在線大量查詢的環境中數據集被LOCK的現象藉此改善查詢的效能。數據庫

  不過有一點千萬要注意的就是,WITH (NOLOCK)的SQL SELECT有可能會形成Dirty Read,就是讀到無效的數據。性能優化

  下面對於SQLSERVER的鎖爭用及nolock,rowlock的原理及使用做一個簡單描述:服務器

鎖爭用的描述併發

  那些不只僅使用行級鎖的數據庫使用一種稱爲混和鎖(lock escalation)的技術來獲取較高的性能。除非很明確知道是針對整個數據表,不然這些數據庫的作法是開始使用行級鎖, 而後隨着修改的數據增多,開始使用大範圍的鎖機制。post

  不幸的是,這種混和鎖的方法會產生和放大新的問題:死鎖。若是兩個用戶以相反的順序修改位於不一樣表的記錄,而這兩條記錄雖然邏輯上不相關, 可是物理上是相鄰的,操做就會先引起行鎖,而後升級爲頁面鎖。這樣, 兩個用戶都須要對方鎖定的東西,就形成了死鎖。性能

例如:測試

  用戶A修改表A的一些記錄,引起的頁面鎖不光鎖定正在修改的記錄,還會有不少其它記錄也會被鎖定。優化

  用戶B修改表B的一些記錄,引起的頁面鎖鎖定用戶A和其它正在修改的數據。url

  用戶A想修改用戶B在表B中鎖定(並不必定正在修改的)數據。

  用戶B想修改或者僅僅想訪問用戶A在表A中鎖定(並不必定正在修改)的數據。

  爲了解決該問題,數據庫會常常去檢測是否有死鎖存在,若是有,就把其中的一個事務撤銷,好讓另外一個事務能順利完成。通常來講,都是撤銷 那個修改數據量少的事務,這樣回滾的開銷就比較少。使用行級鎖的數據庫 不多會有這個問題,由於兩個用戶同時修改同一條記錄的可能性極小,並且因爲極其偶然的修改數據的順序而形成的鎖也少。

  並且,數據庫使用鎖超時來避免讓用戶等待時間過長。查詢超時的引入也是爲了一樣目的。咱們能夠從新遞交那些超時的查詢,可是這隻會形成數據庫的堵塞。若是常常發生超時,說明用戶使用SQL Server的方式有問題。正常狀況是不多會發生超時的。

  在服務器負載較高的運行環境下,使用混合鎖的SQL Server鎖機制,表現不會很好。 緣由是鎖爭用(Lock Contention)。鎖爭用形成死鎖和鎖等待問題。在一個多用戶系統中,不少用戶會同時在修改數據庫,還有更多的用戶在同時訪問數據庫,隨時會產生鎖,用戶也爭先恐後地獲取鎖以確保本身的操做的正確性,死鎖頻繁發生,這種情形下,用戶的心情可想而知。

  確實,若是隻有少許用戶,SQL Server不會遇到多少麻煩。內部測試和發佈的時候,因爲用戶較少,也很難發現那些併發問題。可是當激發幾百個併發,進行持續不斷地INSERT,UPDATE,以及一些 DELETE操做時,如何觀察是否有麻煩出現,那時候你就會手忙腳亂地去解鎖。

 

鎖爭用的解決方法

  SQL Server開始是用行級鎖的,可是常常會擴大爲頁面鎖和表鎖,最終形成死鎖。

  即便用戶沒有修改數據,SQL Server在SELECT的時候也會遇到鎖。幸運的是,咱們能夠經過SQL Server 的兩個關鍵字來手工處理:NOLOCK和ROWLOCK。

它們的使用方法以下:

 

 SELECT COUNT(UserID)
  FROM Users WITH (NOLOCK)
  WHERE Username LIKE 'football'

UPDATE Users WITH (ROWLOCK)
SET Username = 'admin' WHERE Username = 'football'

NOLOCK的使用

  NOLOCK能夠忽略鎖,直接從數據庫讀取數據。這意味着能夠避開鎖,從而提升性能和擴展性。但同時也意味着代碼出錯的可能性存在。你可能會讀取到運行事務正在處理的無須驗證的未遞交數據。 這種風險能夠量化。

ROWLOCK的使用

  ROWLOCK告訴SQL Server只使用行級鎖。ROWLOCK語法可使用在SELECT,UPDATE和DELETE語句中,不過 我習慣僅僅在UPDATE和DELETE語句中使用。若是在UPDATE語句中有指定的主鍵,那麼就老是會引起行級鎖的。可是當SQL Server對幾個這種UPDATE進行批處理時,某些數據正好在同一個頁面(page),這種狀況在當前狀況下 是頗有可能發生的,這就象在一個目錄中,建立文件須要較長的時間,而同時你又在更新這些文件。當頁面鎖引起後,事情就開始變得糟糕了。而若是在UPDATE或者DELETE時,沒有指定主鍵,數據庫固然認爲不少數據會收到影響,那樣 就會直接引起頁面鎖,事情一樣變得糟糕。

下面寫一個例子,來講明一下NOLOCK的做用,這裏使用一個有一萬多條的數據庫來測試,先不用NOLOCK來看一下:

declare @start DATETIME;
declare @end DATETIME;
SET @start = getdate();
select * from Captions_t18;
SET @end = getdate();
select datediff(ms,@start,@end);

這裏爲了是效果更加明顯,使用了Select * ,來看一下執行結果,以下圖:

這裏顯示的使用時間是34720ms,下面使用NOLOCK來看一下:

declare @start DATETIME;
declare @end DATETIME;
SET @start = getdate();
select * from Captions_t18 with (NOLOCK);
SET @end = getdate();
select datediff(ms,@start,@end);

運行結果以下圖:

此次使用的時間是2563ms,差距體現出來了吧。我的感受時間不該該差這麼多,總之性能是提升了很多。你們多多測試看看吧~~

 

參考文章:http://blog.sina.com.cn/s/blog_7034dbe00100ll9n.html

相關文章
相關標籤/搜索