更快地上传到数据库

时间:2012-10-23 13:19:57

标签: c# sql sqlcommand

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

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

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

CommandString中:

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

4 个答案:

答案 0 :(得分:2)

  1. 在for(int i = 0; i&lt; urlList.Count; i ++)
  2. 之外创建命令和参数创建
  3. 还在事务中创建插入
  4. 如果可以创建存储过程并将参数作为DataTable传递。

答案 1 :(得分:2)

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

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

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

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

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

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

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

答案 2 :(得分:1)

将INSERT命令逐个发送到数据库将真正使整个过程变慢,因为往返数据库服务器。如果您担心性能,则应考虑使用批量插入策略。你可以:

  1. 使用BULK INSERT理解的格式生成包含所有信息的平面文件。
  2. 使用BULK INSERT命令将该文件导入数据库(http://msdn.microsoft.com/en-us/library/ms188365(v=sql.90).aspx)。
  3. 聚苯乙烯。我猜你说SQL时你正在使用MS SQL Server。

答案 3 :(得分:-1)

为什么不从单独的线程运行 uploadContent()方法。
这样,您无需担心查询执行的时间。