2

我有一些代码在程序生命结束时将 6 个不同列表的全部内容上传到数据库中。问题是,它们是包含大约 14,000 个项目的并行列表,我必须为每个单独的项目运行插入查询。这需要很长时间,有没有更快的方法来做到这一点?以下是相关代码的示例:

    public void uploadContent()
    {
        var cs = Properties.Settings.Default.Database;
        SqlConnection dataConnection = new SqlConnection(cs);
        dataConnection.Open();

        for (int i = 0; i < urlList.Count; i++)
        {
            SqlCommand dataCommand = new SqlCommand(Properties.Settings.Default.CommandString, dataConnection);
            try
            {
                dataCommand.Parameters.AddWithValue("@user", userList[i]);
                dataCommand.Parameters.AddWithValue("@computer", computerList[i]);
                dataCommand.Parameters.AddWithValue("@date", timestampList[i]);
                dataCommand.Parameters.AddWithValue("@itemName", domainList[i]);
                dataCommand.Parameters.AddWithValue("@itemDetails", urlList[i]);
                dataCommand.Parameters.AddWithValue("@timesUsed", hitsList[i]);

                dataCommand.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                using (StreamWriter sw = File.AppendText("errorLog.log"))
                {
                    sw.WriteLine(e);
                }
            }

        }
        dataConnection.Close();
    }

这是代码从配置文件中提取的命令字符串:

命令字符串:

INSERT dbo.InternetUsage VALUES (@user, @computer, @date, @itemName, @itemDetails, @timesUsed)
4

4 回答 4

2
  1. 在 for (int i = 0; i < urlList.Count; i++) 之外创建命令和参数
  2. 同时在事务中创建插入
  3. 如果可能,创建一个存储过程并将参数作为 DataTable 传递。
于 2012-10-23T13:25:43.250 回答
2

正如@alerya 的回答中所述,执行以下操作会有所帮助(在此处添加说明)

1)在for循环之外创建命令和参数 由于每次都使用相同的命令,每次都重新创建命令没有意义。除了创建一个新对象(这需要时间)之外,还必须在每次为多个事物(表存在等)创建命令时验证该命令。这引入了很多开销。

2)将插入放入 事务中将所有插入放入事务中会加快速度,因为默认情况下,不在事务中的命令将被视为自己的事务。因此,每次插入内容时,数据库服务器都必须验证它刚刚插入的内容是否实际保存(通常在硬盘上,受磁盘速度的限制)。但是,当多个 INSERT 在一个事务中时,只需要执行一次检查。

根据您已经展示的代码,这种方法的缺点是一个错误的 INSERT 会破坏一堆。这是否可以接受取决于您的具体要求。

除了 您真正应该做的另一件事(尽管这不会在短期内加快速度)是正确使用 IDisposable 接口。这意味着要么在所有 IDisposable 对象(SqlConnection、SqlCommand)上调用 .Dispose(),或者在理想情况下将它们包装在 using() 块中:

using( SqlConnection dataConnection = new SqlConnection(cs) 
{
    //Code goes here
}

这将防止这些点的内存泄漏,如果您的循环变得太大,这将很快成为一个问题。

于 2012-10-23T13:41:41.570 回答
1

一个一个地向数据库发送 INSERT 命令确实会使整个过程变慢,因为要往返于数据库服务器。如果您担心性能,您应该考虑使用批量插入策略。你可以:

  1. 以 BULK INSERT 可以理解的格式生成包含所有信息的平面文件。
  2. 使用 BULK INSERT 命令将该文件导入数据库 ( http://msdn.microsoft.com/en-us/library/ms188365(v=sql.90).aspx )。

附言。我猜当您说 SQL 时,您使用的是 MS SQL Server。

于 2012-10-23T13:39:02.337 回答
-1

为什么不从单独的线程 运行您的uploadContent()方法。
这样您就不必担心查询需要多少时间来执行。

于 2012-10-23T13:31:22.720 回答