Более быстрый способ обработки множества потоков, обновляющих / добавляющих данные в базу данных SQL - PullRequest
0 голосов
/ 03 июля 2011

BackGround: я выполняю около 80 потоков, каждый поток будет непрерывно добавлять данные в базу данных (около 30 000 раз для каждого потока) (я использую SQL Server Express).но медленной частью программы является TableAdapter.Update part.

Почему я задаю этот вопрос: узнать о каких-либо более быстрых способах обновления базы данных.

О чем я думаю:Это для того, чтобы назначить новую компактную базу данных каждому потоку и после каждых 10 тыс. Записей синхронизироваться с фактической базой данных (но я не знаю, как сделать какую-либо ее часть)

Разбитый до чистого кода:

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 ]

2 голосов
/ 03 июля 2011

Вы можете сделать несколько вещей.

Вы можете выполнить массовую загрузку либо с помощью SqlBulkCopy, либо (начиная с SqlServer 2008) вы можете передать таблицу в хранимую процедуру, а хранимая процедура может использовать команду MERGE INTO sql для запуска вставки или обновления таблицы.

Используя этот метод, мы можем получить около 200 тыс. Вставок за 10 секунд.

1 голос
/ 03 июля 2011

Вы можете использовать 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 будет намного быстрее, так как он предназначен именно для этой конкретной проблемы.

0 голосов
/ 03 июля 2011

Честно говоря, я бы совмещал 80 потоков и начинал с 1 или 2, давал им больше работы, проводил тестирование производительности и нагрузки, чтобы увидеть, сколько они могут сделать и как быстро.Это даст вам реальное представление о том, сколько они могут сделать за раз, чтобы определить, действительно ли вам нужно больше потоков.Если вам нужно больше потоков, делайте это постепенно.2, 3, 4 .. 80 темы?Это кажется мне безумным, потому что у меня нет ни одного процесса (кроме процессов основной системы), который бы достигал почти 80 потоков, включая SQL Server Enterprise R2 и другие вещи. Если ваша причина использования 80 потоков "невелика"причина ", то вы, вероятно, должны переосмыслить это.Не забывайте, что у вас все еще есть ограничения производительности из-за пропускной способности, задержек и других связанных с сетью вещей.Говоря о производительности и вещах, которые могут привести к ее замедлению, подумайте «что осталось?».

Мой совет по этому вопросу - тестирование производительности.Возможно, даже исследуйте объекты, которые вы используете, поскольку они могут быть дорогостоящими объектами, и, возможно, посмотрите на некоторые альтернативные методы для продвижения ваших данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...