更快速地处理许多线程更新/添加数据到SQL数据库

时间:2011-07-03 05:40:31

标签: c# .net multithreading sql-server-2008 ado.net

BackGround:我正在执行大约80个线程,每个线程将不断向数据库添加数据(每个线程大约30k次)(我正在使用sql server express)。但程序的缓慢部分是TableAdapter.Update部分。

为什么我问这个问题:要知道更新数据库的更快方法。

我在想:是为每个线程分配一个新的压缩数据库,每10k个条目与实际数据库同步后。(但我不知道如何做任何部分)

破碎到骨干代码:

class Do : Form1
{
    public int i;
    public void FillTable(string[] ws)
    {
        DataRow row = database1DataSet1.Result.NewResultRow();
        row["one"] = ws[0];

        try
        {
            database1DataSet1.Result.Rows.Add(row);
        }
        catch {}
        lock (this)
        {
            try { resultTableAdapter.Update(database1DataSet1.Result); }
            catch { }
        }
    }

    public void start()
    {
        for (;;) //Run about 30k to 40k times
        {
          string[] ws = SOMEFUNC();
          FillTable(ws);
        }   
    } 
}

致电代码:

Do[] case1 = new Do[80];

Thread[] t = new Thread[80];
for (int ij = 0; ij < 80; ij++)
{
    case1[ij] = new Do();
    case1[ij].i = ij;
    t[ij] = new Thread(new ThreadStart(case1[ij].start));
    t[ij].Start();
}

有什么想法吗?

编辑:其中一个解决方案:http://www.dotnetcurry.com/ShowArticle.aspx?ID=323

3 个答案:

答案 0 :(得分:2)

你可以做多件事。

您可以通过SqlBulkCopy进行批量加载,或者(因为您在SqlServer 2008上)可以将表传递给存储过程并让存储过程使用MERGE INTO sql命令来快速插入或更新表。

我们可以使用这种方法在10秒内获得大约200k的插入。

答案 1 :(得分:1)

您可以使用Dapper代替TableAdapter。它将消除大部分开销。

特别是你可以使用一个可枚举的助手:

// begin tran
var items = new[] {{a=1,b=2},{a=2,b=3}};
cnn.Execute("insert table(a,b) values(@a,@b)", items); 
// commit tran

Dapper会很快,但SqlBulkCopy会更快 ,因为它专为此特定问题而设计。

答案 2 :(得分:0)

老实说,我会赞成80个线程,从1或2开始,给他们更多的工作,并做一些性能和负载测试,看看他们能做多少,以及多快。这将让你真正了解他们在x时间内可以做多少,以确定你是否真的需要更多线程。如果确实需要更多线程,请逐步执行。 2,3,4 .. 80线程?这对我来说似乎很疯狂,因为我没有一个进程(除了核心系统进程之外)甚至可以达到接近80个线程,包括SQL Server Enterprise R2和其他东西..如果你使用80个线程的原因是“不大”理由“,那么你应该重新考虑一下。不要忘记,由于带宽,延迟和其他与网络相关的问题,您仍然存在性能限制。在谈论表演和可能导致其放慢速度的事情时,请考虑“剩下的是什么?”。

增量性能测试是我对此的建议。甚至可能对您正在使用的对象进行研究,因为它们可能是昂贵的对象,并且可能会研究一些替代方法来推动您的数据。