C# 不同DBContext的并行执行比非并行版本慢

C# 不同DBContext的并行执行比非并行版本慢,c#,entity-framework,sql-server-2012,task-parallel-library,C#,Entity Framework,Sql Server 2012,Task Parallel Library,我有一个简单的表,有两列(一列是identity,另一列是一些char列): 我们有一个函数,可以执行一些长时间运行的操作。下面是一些伪代码: void doWork() { using(context) { doLongPart1(context); ... doLongPartN(context); } } 现在,我正试图使用各自的上下文将它们隔离在单独的任务中。但令人惊讶的是,有任务的版本比没有任务的版本需要更多的时

我有一个简单的表,有两列(一列是
identity
,另一列是一些
char
列):

我们有一个函数,可以执行一些长时间运行的操作。下面是一些伪代码:

void doWork()
{
    using(context)
    {
        doLongPart1(context);
        ...
        doLongPartN(context);
    }
}
现在,我正试图使用各自的上下文将它们隔离在单独的任务中。但令人惊讶的是,有任务的版本比没有任务的版本需要更多的时间。我在这里插入
10000
行。时间是:
~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.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);
}
但对我来说什么都不管用。有人能给我指出正确的方向吗?

一个c#程序不会让你的数据库更快

如果您的问题是数据库中插入操作的速度,那么将其并行化并不能消除瓶颈,它仍然是数据库中的插入操作

你通常可以看到两(3)件事

1) 数据库服务器中更快的驱动器/SSD(和或更多ram)

2) 减少索引的数量,因为在插入操作中也必须更新这些索引

对于某些操作,您甚至可以删除索引,插入所需的所有数据,然后重新创建索引,因为每次插入行时,索引只会更新一次

更新:现在我更详细地了解您的数字,在我见过的应用程序中,每秒1000次查询并不少见


更新2:一种可能的解决方案是大容量插入,因为即使使用存储过程,您的开销也在查询数量上,而不是在查询中(假设您没有索引和计算列)

连接数据库和/或表上的锁的开销很可能与此有关。@LasseV.Karlsen,我正在与DBA进行检查,很快会通知您。我也会查一查。选择不应该给我一个区别吗?好吧,事实证明我已经达到了Sql引擎的最大值,所以并行执行没有区别。两人都在以尽可能快的速度工作。在数据库级别上也没有锁。现在我意识到你实际上是正确的。在这种情况下,我达到了极限,并行性没有给我任何东西。这只是一个测试,但在实际情况下,它应该给我的好处,因为有插入选择,计算,细节等。
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);
}
sp_configure 'show advanced options', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO
sp_configure 'max degree of parallelism', 8;
GO
RECONFIGURE WITH OVERRIDE;
GO