我有一个巨大的批处理操作,每隔几个月运行一次,解析并从文本文件导入Sql Server数据库。这个过程需要几天的时间才能完成,我正在研究如何加快它的速度。大约1/3的时间是解析文本,并在数据库I/O中分配2/3的时间。多线程以获得最佳性能问题
我认为一个简单的解决方案是将它们分成单独的线程。所以,当一个线程写入数据库时,另一个线程可以解析文本。我改变了代码来建立一个需要被执行的SqlCommand对象列表,然后这些对象被传递给一个新的线程,一旦解析完成就执行。
对于在单个线程中执行一批SqlCommand对象的小样本需要37秒,当我切换到在单独的线程中执行这些过程时,我感到很惊讶,这个过程大量减慢,总共需要63.34秒。我做了一些探索,最终决定在Visual Studio中运行一些性能分析。我运行Instrumentation来测量多线程版本的时序,并在31.04秒内运行时感到惊讶。我多次重复所有测试,结果大致相同。因此,与运行性能分析时相比,工作负载的分裂可以提高性能,但是如果不运行性能分析,它会变慢。
如果有人可以帮助指出可能是什么原因导致这种情况,我应该在哪里寻找解决方法,那太棒了!
测试运行在6核心主机上运行的四核VMware虚拟机上。
编辑:进一步研究了这个问题后,违规行似乎与解析有关,与数据库无关,主要是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();
}
}
}
什么是您使用的.net框架版本? –
当你计时63.34秒时,你是否正在运行调试器?点击ctrl + f5运行时没有调试器,只是按下f5,它将连接调试器运行,这会降低性能 – BrandonAGr
@BrandonAGr - 这似乎解决了这个问题。如果您将其作为答案张贴,那么我会将其标记为已回答。这并不能解释为什么在连接调试器的情况下运行多个线程应该以仅运行一个线程的速度运行一半。这是真正的奥秘。 –