2010-06-15 45 views
2

有一個存儲過程:併發在SQL Server 2008

CREATE PROCEDURE [dbo].[TestProc] 
AS 
BEGIN 
    SET NOCOUNT ON; 

    create table #thistable (rid char(32)) 
    insert into #thistable(rid) 
    select A0RID from tblCdbA0 with (nolock) 
    END 

當單獨執行的過程所花費400-500毫秒,但是,當10個線程的並行執行相同的程序,然後在第一個線程在1300毫秒內完成,最後 - 在6000毫秒內,平均值爲4800毫秒。 正如你所看到的,當其他線程執行完成時,線程等待的地方沒有鎖定。而且,服務器CPU的加載時間小於100%,即有足夠的資源來同時執行它們。那怎麼可能?

編輯:發現有關併發插入一個很好的文章: Resolving PAGELATCH Contention on Highly Concurrent INSERT Workloads

+0

它似乎插入8次相同的東西。那是對的嗎?如果是這樣的話,在8行派生表上進行笛卡爾連接會更快(或者這只是一個用於測試的演示)? – 2010-06-15 15:30:01

+0

感謝您的評論,問題不在於代碼性能,而在於併發性:爲什麼當10個線程執行這個簡單的過程時,它似乎被阻塞了? (完全是一個演示) – Tim 2010-06-15 15:32:54

+0

@tim - 你有沒有嘗試過在'sys.dm_os_wait_stats'上看到什麼是等待?注意:爲了在測試之前清除這個問題,你可以做'DBCC SQLPERF(「sys.dm_os_wait_stats」,CLEAR)' – 2010-06-15 15:41:08

回答

3

首先,CPU不是數據庫中唯一的資源。您發佈的查詢插入到tempdb中的#temp表中,該表需要以下資源:

  • tempdb SGAM/GAM分配。
  • tempdb的日誌
  • 緩衝池
  • tempdb數據庫IO

所以,如果你有400-500毫秒一個線程和10個線程在6000毫秒完成,這並不讓我感到吃驚。您請求10倍的工作量(即將這些#temp表寫入磁盤的10倍以上),因此預計需要4000-5000毫秒。額外的1000毫秒可能來自爭用(線程競爭相同的資源)。

最終,您需要測量花費的時間,請參閱SQL Server 2005 Waits and Queues以瞭解如何分析問題的好方法。

+0

如果我冒險猜測,我會說限制因素是日誌刷新速度。一個線程需要400-500毫秒,因爲這是將要插入的數據寫入LDF文件需要多少時間,並且只有在提交(磁盤上的日誌被強化)之後,語句才能返回。所以10個線程寫10倍,將多10倍。 – 2010-06-15 15:53:17

+0

評論看起來像合理的假設,有沒有辦法避免寫入日誌,以便檢查它?在任何情況下,它是有點奇怪,服務器無法寫入並行登錄.. – Tim 2010-06-15 15:59:33

+0

當然,服務器並行寫日誌:)但如果您的硬盤130Mb /秒最大傳輸(這是通常的一個消費者驅動器的最大/最佳傳輸速率),那麼一個查詢將使用全部130 Mb /秒,10個線程將分享它並獲得每個約13Mb /秒。 – 2010-06-15 16:41:21

2

爲什麼選擇從同一個表8次,只複製行,一旦你讓他們在第一時間,試試這個:

CREATE PROCEDURE [dbo].[TestProc] 
AS 
SET NOCOUNT ON; 

create table #thistable (rid char(32)) 

;WITH AllNumbers AS 
(
    SELECT 1 AS Number 
    UNION ALL 
    SELECT Number+1 
     FROM AllNumbers 
     WHERE Number<8 
) 
insert into #thistable 
     (rid) 
    select A0RID 
     from tblCdbA0    t with (nolock) 
     INNER JOIN AllNumbers  a ON 1=1 

RETURN 0 
GO 

如果使用UNION執行此操作,則每個線程有8個表掃描,這會增加並影響性能。

+0

感謝您的評論,基本上這些代碼僅用於演示,它的性能本身並不有趣。問題在於併發性。 – Tim 2010-06-15 15:48:01

+1

@Tim,在你的問題中,你引用特定的執行時間並給出一個特定的(奇怪的)查詢,但你還需要其他的東西嗎?也許你需要修改你的問題,但我不確定你在做什麼。也許你是在像@Remus Rusanu的回答那樣不太具體的事情之後。如果是這樣,你真的希望SQL Server具有無限的讀/寫帶寬來同時處理所有IO(針對每個線程)嗎? – 2010-06-15 15:54:21