5k + SQL插入需要很长时间 - 我该如何改进它?

时间:2016-01-05 09:56:05

标签: sql vb.net sql-server-2012 bulkinsert sqlperformance

通常我只运行少于50的循环,运行正常。现在我正在努力扩大规模并且用5k +它需要几分钟。

Public Shared Sub Add(type As BufferType, objIDs As List(Of Integer), userToken As String)
    Dim timeInUTCSeconds As Integer = Misc.UTCDateToSeconds(Date.Now)
    For Each objID As Integer In objIDs
        Dim insertStmt As String = "IF NOT EXISTS (SELECT ObjectID From " & TableName(type) & " where ObjectID = " & objID & " and UserToken = '" & userToken.ToString & "')" & _
        " BEGIN INSERT INTO " & TableName(type) & "(ObjectID,UserToken,time) values(" & objID & ", '" & userToken.ToString & "', " & timeInUTCSeconds & ") END" & _
        " ELSE BEGIN UPDATE " & TableName(type) & " set Time = " & timeInUTCSeconds & " where ObjectID = " & objID & " and UserToken = '" & userToken.ToString & "' END"
        DAL.SQL.Insert(insertStmt)
    Next
End Sub

3 个答案:

答案 0 :(得分:1)

最好的选择是将整个工作转移到SQL端。将 objIDs 列表作为表参数传递给存储过程,并使用MERGE..UPDATE..INSERT语句。

如果您需要VB侧码,您可以进行多项优化。

  • SQL参数。必须这样做。
  • 检查DAL.SQL类是否正确处理连接。
  • 从命令构建单个批处理并将其作为整批运行。

答案 1 :(得分:1)

(我假设SQL Server是一个合理的最新版本,因为它是一个.Net问题。)

  1. 如果可能的话,将其移动到一个存储过程,该存储过程接受表值参数或带分隔符的ID字符串。
  2. 参数化您的查询。当DBMS执行一串没有参数的代码时,它无法确定哪些位是常量以及哪些是参数 - 因此每次都会计算出一个新的执行计划。使用数据参数,它可以重用执行计划并加快运行速度。
  3. 由于重复性很大的工作,连接延迟可能会成为一个非常大的问题。如果真的必须从调用应用程序执行类似这样的ad-hoc SQL(我不会这样做,但这是你的项目),请尝试批处理语句并执行它们。而不是发出5000个个人连接。应该快得多。

答案 2 :(得分:1)

您应始终使用SQLBULKCOPY插入大量数据。您可以查看始终认为here作为将大量数据插入表格的最佳做法。

演示代码将使您的事实清晰,这取自here

private static void PerformBulkCopy()
{
    string connectionString =
            @"Server=localhost;Database=Northwind;Trusted_Connection=true";
    // get the source data
    using (SqlConnection sourceConnection =
            new SqlConnection(connectionString))
    {
        SqlCommand myCommand =
            new SqlCommand("SELECT * FROM tablename", sourceConnection);
        sourceConnection.Open();
        SqlDataReader reader = myCommand.ExecuteReader();

        // open the destination data
        using (SqlConnection destinationConnection =
                    new SqlConnection(connectionString))
        {
            // open the connection
            destinationConnection.Open();

            using (SqlBulkCopy bulkCopy =
            new SqlBulkCopy(destinationConnection.ConnectionString))
            {
                bulkCopy.BatchSize = 500;
                bulkCopy.NotifyAfter = 1000;
                bulkCopy.SqlRowsCopied +=
                    new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopied);
                bulkCopy.DestinationTableName = "Tablename";
                bulkCopy.WriteToServer(reader);
            }
        }
        reader.Close();
    }
}

另外,请不要忘记阅读与 Batchsize

相关的文档

希望有所帮助。