使用.NET将1,000,000条记录更新(填充)到数据库中的最快方法

时间:2013-06-24 17:27:18

标签: c# .net sql nosql localdb

我使用此代码将100万条记录插入数据库中的空表。好吧,如果没有太多代码,我将从我已与数据交互的点开始,并将模式读入DataTable

所以:

DataTable returnedDtViaLocalDbV11 = DtSqlLocalDb.GetDtViaConName(strConnName, queryStr, strReturnedDtName);

现在我们有returnedDtViaLocalDbV11允许创建一个新的DataTable作为源数据库表的克隆:

DataTable NewDtForBlkInsert = returnedDtViaLocalDbV11.Clone();

Stopwatch SwSqlMdfLocalDb11 = Stopwatch.StartNew();
NewDtForBlkInsert.BeginLoadData();

for (int i = 0; i < 1000000; i++)
{
   NewDtForBlkInsert.LoadDataRow(new object[] { null, "NewShipperCompanyName"+i.ToString(), "NewShipperPhone" }, false);
}
NewDtForBlkInsert.EndLoadData();

DBRCL_SET.UpdateDBWithNewDtUsingSQLBulkCopy(NewDtForBlkInsert, tblClients._TblName, strConnName);

SwSqlMdfLocalDb11.Stop();

var ResSqlMdfLocalDbv11_0 = SwSqlMdfLocalDb11.ElapsedMilliseconds;

此代码在 5200ms 中填充100万条记录到嵌入式SQL数据库(localDb)。其余的代码只是实现了bulkCopy,但无论如何我都会发布它。

 public string UpdateDBWithNewDtUsingSQLBulkCopy(DataTable TheLocalDtToPush, string TheOnlineSQLTableName, string WebConfigConName)
 {
    //Open a connection to the database. 
    using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings[WebConfigConName].ConnectionString))
    {
       connection.Open();

       // Perform an initial count on the destination table.
       SqlCommand commandRowCount = new SqlCommand("SELECT COUNT(*) FROM "+TheOnlineSQLTableName +";", connection);
       long countStart = System.Convert.ToInt32(commandRowCount.ExecuteScalar());

       var nl = "\r\n";
       string retStrReport = "";
       retStrReport = string.Concat(string.Format("Starting row count = {0}", countStart), nl);
       retStrReport += string.Concat("==================================================", nl);
       // Create a table with some rows. 
       //DataTable newCustomers = TheLocalDtToPush;

       // Create the SqlBulkCopy object.  
       // Note that the column positions in the source DataTable  
       // match the column positions in the destination table so  
       // there is no need to map columns.  
       using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
       {
          bulkCopy.DestinationTableName = TheOnlineSQLTableName;

          try
          {
             // Write from the source to the destination.
             for (int colIndex = 0; colIndex < TheLocalDtToPush.Columns.Count; colIndex++)
             {
                bulkCopy.ColumnMappings.Add(colIndex, colIndex);
             }
             bulkCopy.WriteToServer(TheLocalDtToPush);
          }

          catch (Exception ex)
          {
             Console.WriteLine(ex.Message);
          }
       }

       // Perform a final count on the destination  
       // table to see how many rows were added. 
       long countEnd = System.Convert.ToInt32(
       commandRowCount.ExecuteScalar());

       retStrReport += string.Concat("Ending row count = ", countEnd, nl);
       retStrReport += string.Concat("==================================================", nl);
       retStrReport += string.Concat((countEnd - countStart)," rows were added.", nl);
       retStrReport += string.Concat("New Customers Was updated successfully", nl, "END OF PROCESS !");
       //Console.ReadLine();
       return retStrReport;
   }
}

通过与SQL服务器的连接尝试它大约7000毫秒(充其量)&amp;平均约7700毫秒。另外通过一个随机的kv nosql数据库花了大约40秒(实际上我甚至没有记录它,因为它通过x2的sql变种)。那么...有没有比我在代码中测试更快的方式?

修改

我正在使用win7 x64 8gb ram,最重要的是我应该认为(因为i5 3ghz)现在还不是很好 Raid-0上的x3 500Gb Wd工作做得更好 但我只想说你是否会检查你的电脑 虽然只是将它与配置中的任何其他方法进行比较

8 个答案:

答案 0 :(得分:2)

你试过SSIS吗?我从未编写过带有loacldb连接的SSIS包,但这是SSIS应该非常适合的那种活动。

如果您的数据源是SQL Server,另一个想法是设置链接服务器。不确定这是否适用于localdb。如果您可以设置链接服务器,则可以一起绕过C#并使用INSERT ... SELECT ... FROM ... SQL语句加载数据。

答案 1 :(得分:1)

删除循环...在SQL中,尝试创建一个包含100万行的表...并且左连接使用它来插入/选择数据

答案 2 :(得分:0)

尝试发送它而不将其存储在数据表中。

请参阅本文末尾的示例,该示例允许您使用枚举器http://www.developerfusion.com/article/122498/using-sqlbulkcopy-for-high-performance-inserts/

执行此操作

答案 3 :(得分:0)

如果您只是创建无意义的数据,请创建一个存储过程,然后通过.net

调用它

如果您要传递真实数据,再次将其传递给存储过程会更快,但您最好放弃该表并使用数据重新创建它。

如果一次插入一行,则需要比一次插入所有行更长的时间。如果要编写索引,则需要更长的时间。

答案 4 :(得分:0)

您可以使用Dapper.NET。 Dapper是一个微型ORM,执行查询并将结果映射到强类型列表。 计算机软件中的对象关系映射(ORM,O / RM和O / R映射)是一种用于在面向对象的编程语言中在不兼容类型系统之间转换数据的编程技术。这实际上创建了一个可以在编程语言中使用的“虚拟对象数据库”

欲了解更多信息:

结帐https://code.google.com/p/dapper-dot-net/

GitHub存储库:https://github.com/SamSaffron/dapper-dot-net 希望它有所帮助..

答案 5 :(得分:0)

为要保存到数据库中的所有行创建单个XML文件。将此XML传递给SQL存储过程并仅将所有记录保存在一个调用中。 但是必须编写存储过程,以便它可以读取所有读取然后插入到表中。

答案 6 :(得分:0)

如果这是一个新项目,我建议您使用Entity Framework。在这种情况下,您可以创建一个List&lt;&gt;使用包含所需数据的对象,然后将其完全添加到相应的表中。 这样,您可以快速获取所需数据,然后立即将其发送到数据库。

答案 7 :(得分:0)

我同意Mike对SSIS的看法,但它不适合您的环境,但是对于涉及跨服务器调用和通用数据流程的ETL进程,它是一个很好的内置工具并且高度集成。

有100万行,您可能需要进行批量插入。根据行大小,除非您批量执行此操作,否则您将无法真正使用存储过程。数据表将非常快速地填充内存,这取决于行的大小。您可以创建一个存储过程并使其具有表类型并调用每X行数,但是当您已经拥有更好,更具伸缩性的解决方案时,我们为什么要这样做。明年可能有5000万行。

我已经使用了SSIS,如果这是一个组织契合我会建议看它,但它不是一次性的答案,不值得依赖。