【问题标题】:Multithreading, DataReaders & Bulk Inserts... Can this app be multithreaded?多线程、数据读取器和批量插入...这个应用程序可以是多线程的吗?
【发布时间】:2012-02-25 22:48:34
【问题描述】:

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

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

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

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

2) 不循环遍历数据行中的每一列,

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

代码

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

【问题讨论】:

    标签: c# multithreading datatable multicore bulkinsert


    【解决方案1】:

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

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

    【讨论】:

    • 遗憾的是,主要问题完全被忽略了——你不能无限地并行化那个广告。
    【解决方案2】:

    如果您消除了初学者的错误,则无需多线程。到处都是大量的慢代码。

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

    慢。永远不要使用名称 - 在循环之外获取索引,然后使用索引。此行有 2 个 (!) 字典查找每行,比行处理花费更多的时间。

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

    【讨论】:

    • 我知道它的草率,虽然我不知道索引会带来性能优势,所以谢谢你,我现在就试试......至于数据表,SqlBulkCopy 只允许数据表、数据行和数据读取器(我不能使用,因为某些记录会导致整个事务失败),这将是我的第一个选择...
    • +1 用于首先整理出较小的优化。可能你发现如果你能更快地开始使用单线程版本,你就不需要使用多线程了
    • & 60张奇怪的表...所以我知道网络问题上的性能不会令人惊讶...这就是为什么在我看来,要走的路似乎是在多个线程中将记录添加到数据表中...再一次,数据集不是我的第一选择/我采取的路线......批量插入似乎是要走的路,所以我用它来完成工作......
    • 至于数据表,SqlBulkCopy 只允许数据表、数据行和数据读取器 - 是的,这就是我在对象上使用 SqlBulkCopy 的原因,你知道的。 DatReaders = IDataReader,实现一个 ObjectDataReader(大约 2 小时的工作)就可以了。我每秒使用来自一个读取器线程的 3 个写入器线程执行 75.000 行插入。我不使用 DataTable,而是使用对象和我自己的 ObjectDataReader。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      当然,如果您不太关心数据完整性(例如您的 ID 不是连续的),您可以更改 table locking 插入类型并启动 3-4 个线程以从桌子。

      【讨论】:

      • 我会尝试你的所有建议,作为一个兴趣点,你能否提供一个关于如何更改表锁定类型的代码示例,从 withing c#.. I'ts从字面上看,我现在第一次听说它,所以似乎有点太空时代:p(我也会咨询谷歌)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 2012-04-01
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多