У меня есть огромная пакетная операция, которая выполняется каждые несколько месяцев при разборе и импорте из текстовых файлов в базу данных Sql Server.Процесс занимает несколько дней, и я ищу способы ускорить его.Примерно 1/3 времени разбора текста и 2/3 времени ввода-вывода базы данных.
Я думал, что простое решение будет разделить их на отдельные потоки.Таким образом, пока один поток пишет в базу данных, другой может анализировать текст.Я изменил код для создания списка объектов SqlCommand, которые должны быть выполнены, после чего они передаются в новый поток для выполнения после завершения синтаксического анализа.
В небольшом примере выполнения пакета объектов SqlCommand водин поток занимает 37 секунд, и я был удивлен, когда переключился на выполнение этих операций в отдельном потоке, что процесс значительно замедлился, что заняло в общей сложности 63,34 секунды.Я немного покопался и в итоге решил провести анализ производительности в Visual Studio.Я запустил Instrumentation для измерения времени в многопоточной версии и был поражен, когда он работал за 31,04 секунды.Я перезапускаю все тесты несколько раз с более или менее одинаковыми результатами.Таким образом, кажется, что при анализе производительности разбивка рабочей нагрузки повышает производительность, но когда анализ производительности не выполняется, он замедляется.
Если кто-то может помочь указать, что может быть причиной этого, и где я должен искать исправлениеэто было бы замечательно!
Тесты выполняются в четырехъядерной виртуальной машине VMware, работающей на 6-ядерном хосте.
edit: если посмотреть дальше, кажется, что ошибочные строките, что связаны с анализом и не имеют ничего общего с БД, в основном fileText.Trim ().Почему они должны работать намного медленнее с подключенным отладчиком, я понятия не имею.
Код запускает новый поток
while (sqlWriterThread != null && sqlWriterThread.ThreadState == ThreadState.Running)
Thread.Sleep(0);
if (sqlWriterThread == null || sqlWriterThread.ThreadState == ThreadState.Stopped)
{
sqlWriterThread = new Thread(new ParameterizedThreadStart(SqlWriterThread));
sqlWriterThread.Name = "SqlWriterThread";
sqlWriterThread.Priority = ThreadPriority.Highest;
}
sqlWriterThread.Start(commandBatch);
Thread.Sleep(0);
Код выполнения запроса
public void SqlWriterThread(object commandBatch)
{
List<SqlCommand> batch = (commandBatch as List<SqlCommand>);
using (SqlConnection connection = new SqlConnection(HelperDatabase.ConnectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
try
{
foreach (SqlCommand cmd in batch)
{
cmd.Connection = connection;
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
cmd.Dispose();
}
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}