3

我有一個簡單的表2列(一個是identity,另一個是一些char列)慢:不同DbContexts的並行執行比平行版本

CREATE TABLE [dbo].[tbl] 
(
    [id] [INT] IDENTITY(1,1) NOT NULL, 
    [col] [CHAR](32) NULL, 
    CONSTRAINT [PK_tbl] PRIMARY KEY CLUSTERED ([id] ASC) 
) 

我們有執行一些長時間運行的功能動作。下面是一些僞代碼:

void doWork() 
{ 
    using(context) 
    { 
     doLongPart1(context); 
     ... 
     doLongPartN(context); 
    } 
} 

現在我試圖找出使用每個自己的上下文中的那些獨立的任務。但令人驚訝的是,任務版本需要更多時間,而沒有任務。我在這裏插入10,000行。時間是:~54000ms版本沒有任務和~57000ms與任務。我使用EF6.0這裏是完整的代碼重現:

初始版本

static void Main(string[] args) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    var c = 10000; 

    var c1 = new TestEntities(); 
    for (int i = 1; i < c/2; i++) 
     c1.tbls.Add(new tbl { col = i.ToString() }); 

    c1.SaveChanges(); 

    var c2 = new TestEntities(); 
    for (int i = c/2; i < c; i++) 
     c2.tbls.Add(new tbl { col = i.ToString() }); 

    c2.SaveChanges(); 

    stopwatch.Stop(); 

    Console.WriteLine(stopwatch.ElapsedMilliseconds); 
    Console.ReadLine(); 
} 

與任務版本

static void Main(string[] args) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    var c = 10000; 
    Task[] tasks = new Task[2]; 

    tasks[0] = Task.Run(() => 
    { 
     var c1 = new TestEntities(); 

     for (int i = 1; i < c/2; i++) 
      c1.tbls.Add(new tbl { col = i.ToString() }); 
     c1.SaveChanges(); 
    }); 

    tasks[1] = Task.Run(() => 
    { 
     var c2 = new TestEntities(); 

     for (int i = c/2; i < c; i++) 
      c2.tbls.Add(new tbl { col = i.ToString() }); 
     c2.SaveChanges(); 
    }); 

    Task.WaitAll(tasks); 

    stopwatch.Stop(); 
    Console.WriteLine(stopwatch.ElapsedMilliseconds); 

    Console.ReadLine(); 
} 

我也試圖通過存儲來做到這一點程序:

CREATE PROC spTbl @s CHAR(32) 
AS 
    INSERT INTO dbo.tbl (col) 
    VALUES (@s) 

和代碼:

static void Main(string[] args) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    var c = 10000; 
    Task[] tasks = new Task[2]; 

    tasks[0] = Task.Run(() => 
    { 
     var c1 = new TestEntities(); 

     for (int i = 1; i < c/2; i++) 
      c1.spTbl(i.ToString()); 
    }); 

    tasks[1] = Task.Run(() => 
    { 
     var c2 = new TestEntities(); 

     for (int i = c/2; i < c; i++) 
      c2.spTbl(i.ToString()); 
    }); 

    Task.WaitAll(tasks); 
} 

我甚至試圖配置SQL Server:

sp_configure 'show advanced options', 1; 
GO 
RECONFIGURE WITH OVERRIDE; 
GO 
sp_configure 'max degree of parallelism', 8; 
GO 
RECONFIGURE WITH OVERRIDE; 
GO 

但沒有什麼對我的作品。任何人都可以將我指向正確的方向嗎?

+0

連接數據庫和/或鎖上的開銷很可能與此有關。 –

+0

@ LasseV.Karlsen,我現在正在與DBA一起檢查,並且很快就會讓你知道。我也會檢查選擇。不應該選擇給我一個區別? –

+0

好吧,事實證明我剛剛達到了我的Sql引擎的最大值,所以並行執行沒有任何區別。兩者都在儘可能地提高速度。在數據庫級別也沒有鎖。 –

回答

1

c#程序不會讓你的數據庫更快。

如果你的問題是在數據庫中插入操作的速度,那麼使它並行不會解除瓶頸,它仍然是數據庫的插入操作。

你可以看看什麼在一般有兩種(3)東西

1)更快的硬盤/ SSD(及以上內存)在你的數據庫服務器

2)減少,因爲這些所有的索引數在插入操作中也必須更新

對於某些操作,您甚至可以刪除索引,插入所需的所有數據,然後重新創建索引,因爲索引只會在每次插入時更新一次行

更新:現在我看看你的號碼更加詳細,每秒1000次查詢在我見過的應用程序中並不罕見。

更新2:一個可行的辦法你可能看是批量插入https://efbulkinsert.codeplex.com/因爲即使你的存儲過程,你的開銷是在查詢的數量,而不是在查詢(假設你沒有索引&計算列)

+0

現在我已經意識到你確實是正確的。在這種情況下,我達到了極限,並行性並沒有給我帶來什麼。這是一個測試,但在真實情況下它應該給我帶來好處,因爲有插入選擇,計算,檢測等。 –