多线程,DataReaders&批量插入...这个应用程序可以多线程吗?

时间:2012-02-03 09:45:45

标签: c# multithreading datatable multicore bulkinsert

是否可以在我的代码中提取代码部分并让它在多个线程中运行?

该应用程序通过网络将数据从FoxPro数据库复制到我们的SQL服务器(文件非常庞大,因此批量复制需要以增量方式进行...

它有效,但我想提高速度。

1)通过让我标记的部分以多个线程运行,或者作为替代,

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.");
        }
    }

更新 我去了第二个选项

我不知道在while(reader.Read())循环内部,我可以执行以下操作。我没有帮助大大提高应用程序性能

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

4 个答案:

答案 0 :(得分:4)

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

  

tblRow [col.Name] = reader [col.Name];

SLOW。永远不要使用名称 - 获取循环外的索引,然后使用索引。这行对于eery行有2(!)字典查找,比行处理花费的时间更长。

DataTables / DataSet开始时效果很慢(糟糕的技术选择),但像这样的代码真的很慢。使用分析器查看其他不良元素。

答案 1 :(得分:1)

这可能不是您所追求的答案,但您是否尝试首先在发布模式下运行控制台应用程序,只需一个try语句,并在阅读器上使用索引?由于SQL Server将成为主要瓶颈,因此可能无法通过多线程来提高速度。

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

答案 2 :(得分:0)

我认为您的用例不会从每个用户的并行中获益。此外,实现代码中使用的OleDbReader的原因也很难。

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

您可以使用Task.Factory.StartNew() method进行此操作。但这会使错误处理变得更复杂,因为当插入失败时,您可能已经处理了更多数据,或者在最坏的情况下,已经有另一个线程正在等待数据库的新插入。

答案 3 :(得分:0)

如果您使用的是.NET 4,可以尝试使用TPL,并将foreach循环转换为类似

的内容
Parallel.ForEach(table.Columns, col => {/*rest of function here */}