2012-02-03 63 views
1

是否有可能提取我的代码中的代码部分,并让它在多个线程中运行?多线程,DataReaders和批量插入...这个应用程序可以多线程?

该应用程序在复制数据从一个FoxPro数据库到我们的SQL服务器通过网络(文件是相当巨大的,因此批量复制需要增量发生......

它的工作原理,但我想颠簸起来的速度的比特。

1)通过任一具有I标记在多个线程中运行,或者作为替代的部分中,

2)通过在数据行的每一列不循环,

我去了第二个选项...(更新下面的代码)

CODE

private void BulkCopy(OleDbDataReader reader, string tableName, Table table) 
    { 
     if (Convert.ToBoolean(ConfigurationManager.AppSettings["CopyData"])) 
     { 
      Console.WriteLine(tableName + " BulkCopy Started."); 
      try 
      { 
       DataTable tbl = new DataTable(); 
       foreach (Column col in table.Columns) 
       { 
        tbl.Columns.Add(col.Name, ConvertDataTypeToType(col.DataType)); 
       } 

       int batch = 1; 
       int counter = 0; 

       DataRow tblRow = tbl.NewRow(); 

       while (reader.Read()) 
       { 
        counter++;     
////This section changed 
         object[] obj = tblRow.ItemArray; 
         reader.GetValues(obj); 
         tblRow.ItemArray = obj; 
////********** 
        tbl.LoadDataRow(tblRow.ItemArray, true); 

        if (counter == BulkInsertIncrement) 
        { 
         Console.WriteLine(tableName + " :: Batch >> " + batch); 
         counter = PerformInsert(tableName, tbl, batch); 
         batch++; 
        } 
       } 

       if (counter > 0) 
       { 
        Console.WriteLine(tableName + " :: Batch >> " + batch); 
        PerformInsert(tableName, tbl, counter); 
       } 

       tbl = null; 
       Console.WriteLine("BulkCopy Success!"); 
      } 
      catch (Exception) 
      { 
       Console.WriteLine("BulkCopy Fail!"); 
      } 
      finally 
      { 
       reader.Close(); 
       reader.Dispose(); 
      } 
      Console.WriteLine(tableName + " BulkCopy Ended."); 
     } 
    } 

UPDATE 我去了第二个选项

我不知道,而同时内部(reader.Read())循环,我可以做下列。 I'T有助于大大提高应用程序的性能

while (reader.Read()) 
{ 
    object[] obj = tblRow.ItemArray; 
    reader.GetValues(obj); 
    tblRow.ItemArray = obj; 
    tbl.LoadDataRow(tblRow.ItemArray, true); 
} 

回答

1

这可能不是你后的答案,但你第一次尝试运行在发布模式的控制台应用程序,只有一个try语句,并使用索引在读者?由于SQL Server将成为主要瓶颈,因此可能无法通过多线程来提高速度。

当然,如果您不太关心数据完整性(例如您的ID不是连续的),您可以更改插入的table locking类型,并旋转3-4个线程以从表中的某些点读取。

+0

我会尝试高清所有的建议,为兴趣点,将你可以提供一个代码示例,了解如何更改表锁定类型,从c#..我现在是第一次听说它,所以似乎有点太空时代:p(我会咨询谷歌作为好吧) – 2012-02-03 10:23:18

0

我不认为你的用例会从平行的每个显着受益。此外,实现您代码中使用的OleDbReader的原因也很难。

但是你可以做的是在SQL Server需要插入数据的时候,在你的循环不会阻塞的新线程上安排插入。

您可以使用Task.Factory.StartNew()method。但是,这会使错误处理更加复杂一些,换句话说,当插入失败时,您可能会处理更多的数据,或者在最糟糕的情况下,已经有另一个线程正在等待数据库的新插入。

4

如果你把初学者的错误去掉了,那么就不需要多线程了。到处都是缓慢的代码。

tblRow [col.Name] =读者[col.Name];

SLOW。切勿使用名称 - 在循环外获取索引,然后使用索引。该行对eery行有2(!)字典查找,比行处理花费更多的时间。 DataTables/DataSet开始时速度很慢(技术选择不好),但是代码很慢,下降。使用分析器查看其他不良元素。

+0

我知道它的松散性,尽管我不知道索引会给性能带来好处,所以谢谢,我现在就试试看...至于数据表,SqlBulkCopy只允许对于数据表,数据行和datareaders(我不能使用,因为一些重新电线导致整个交易失败),这将是我的第一个选择... – 2012-02-03 10:33:15

+1

+1首先对较小的优化进行整理。你可能发现你不需要使用多线程,如果你能以更快的速度获得单线程版本 – 2012-02-03 10:34:30

+0

好吧,更新我的代码使用索引,性能几乎相同,我忘了提及即时通讯在每次传球中做了20 000条记录的批量插入,每张表格有+/- 5mil记录和60多张表格......所以我知道在网络上的表现不会很惊人......这就是为什么在我看来,要走的路线是将记录添加到数据表中发生在多个线程中...再次,数据集wasnt我的第一选择/路线我采取了...批量插入似乎要走的路,所以我把它完成工作...... – 2012-02-03 10:52:45

0

如果您使用.NET 4,你可以尝试使用TPL,和foreach循环转换成类似

Parallel.ForEach(table.Columns, col => {/*rest of function here */} 
+0

令人遗憾的是,主要问题完全被忽略了 - 你无法将无限广告平分。 – TomTom 2012-02-03 10:54:43