Многопоточное приложение для обновления базы данных

У меня есть приложение C#, которое вставляет строки в три отдельные таблицы в базе данных SQL Server. Это массивное пакетное задание (по 2–3 млн. Строк в каждой). Мой код выглядит примерно так (я отредактировал, чтобы удалить ненужные детали):

string sqlCust = "INSERT INTO customer (account, name, last_order) VALUES (@account, @name, @last_order)";
string sqlOrder = "INSERT INTO orders (num, order_date) VALUES (@num, @order_date)"
string sqlOrderLines = "INSERT INTO order_lines (product) VALUES (@prod)"

db.Open();

while (GetNextCust())
{
    using (SqlCommand cmdIns = new SqlCommand(sqlCust, db.Connection))
    {
        cmdIns.Parameters.Add("@account", custAcc);
        cmdIns.Parameters.Add("@name", custName);
        cmdIns.Parameters.Add("@last_order", lastOrder);
        cmdIns.ExecuteNonQuery();
    }

    while (GetNextOrder(custAcc))
    {
         ...

         while (GetNextOrderLine(orderNum)
         {
             ...
         }
    }
}

Процесс находится в автономном режиме, и я хочу поставить в очередь как можно больше работы с базой данных, чтобы увеличить пропускную способность. У меня вопрос, есть ли оптимальное количество потоков (или есть способ узнать, что это может быть - кроме проб и ошибок)? Кроме того, есть ли серьезные предостережения, когда нужно делать что-то подобное с потоками?

5 ответов

Решение

Вам нужно экспериментировать. Если вы читаете и пишете в один источник, оптимальным числом потоков, вероятно, является один. Если вы читаете из нескольких источников и пишете в один, то 2 или 3 могут принести некоторые улучшения.

В вашем случае выше, наиболее значительными победами было бы переключиться с транзакционных вставок на SqkBulkCopy,

К сожалению, метод проб и ошибок - ваш лучший вариант. Трудно предсказать точный оптимальный дизайн заранее, так как здесь нужно учитывать множество факторов. Откуда поступают данные для ваших обновлений? Если они приходят из общего ресурса, то многопоточность может не сильно помочь. Кроме того, дизайн таблицы (ов) вступает в игру. SQL Server - это сложная база данных, это пакетное обновление не обязательно связано с вводом / выводом. Здесь также может быть задействовано сетевое взаимодействие, как и конфигурация SQL Server.

Для оптимального количества потоков, снова проб и ошибок здесь. Я бы начал с двух, а затем попытался бы увеличить это число, даже помимо количества ядер, которое у вас есть. Причина этого в том, что у вас, вероятно, есть сеть между вашим клиентом и сервером. Кроме того, каждый поток должен поддерживать свое соединение с базой данных.

В качестве альтернативы обработке на стороне клиента вы можете загрузить на сервер весь входной файл пакетного задания (или что у вас есть), возможно, с помощью WCF. Тогда вы можете использовать более совершенные механизмы для выполнения пакетного обновления вместо отдельных команд SQL.

Всегда "проверяй и измеряй".

Многопоточные приложения могут работать быстрее только на многоядерных компьютерах.

Если база данных является узким местом, и, вероятно, это так, добавление потоков замедлит процесс, поскольку в дополнение к накладным расходам на переключение задач между потоками база данных будет тратить больше времени на организацию очередей и управление работой из нескольких запросов.

Если вы не выполняете тонну обработки, я предполагаю, что вашим узким местом будет сам диск (база данных). Поэтому, вероятно, оптимальное количество потоков будет равно одному.

Конечно, вам придется иметь дело с людьми, желающими выйти из приложения, когда оно может быть запущено (если это приложение), поэтому вам понадобится какая-то проверка на выход, чтобы своевременно завершить работу.

Что ж, я думаю, что вы можете попробовать какой-то пул соединений, таким образом, для каждого нового пользователя (который вызывает некоторые транзакции БД) вы получите новый поток (я называю их DBBrockers), который предоставит ему доступ к базе данных. Чтобы все это работало, вам понадобится многоядерный компьютер; больше процессоров, больше потоков.

Другие вопросы по тегам