【问题标题】:Why insert statement is slow with SqlCommand?为什么使用 SqlCommand 插入语句很慢?
【发布时间】:2018-07-05 14:43:48
【问题描述】:

我正在使用SqlCommand向数据库插入多条记录,但是插入2000条记录需要很长时间,我做了以下代码:

using (SqlConnection sql = new SqlConnection(connectionString))
{
    using (SqlCommand cmd = new SqlCommand(query, sql))
    {
        sql.Open();
        int ff = 0;
        while (ff < 2000)
        {
            cmd.ExecuteNonQuery();//It takes 139 milliseconds approximately
            ff++;
            Console.WriteLine(ff);
        }

    }
}

但是当我在 SSMS(Sql Server Management Studio) 中执行以下脚本时,2000 条记录会在 15 秒内存储:

declare @i int;
set @i=1

while (@i)<=2000
begin
    set @i=@i+1
    INSERT INTO Fulls (ts,MOTOR,HMI,SET_WEIGHT) VALUES ('2018-07-04 02:56:57','0','0','0'); 
end

发生了什么事? 为什么执行语句这么慢?

补充:

-数据库是托管在 Microsoft Azure 中的 SQL 数据库。

-我的网络加载速度是 20 Mbits。

-以上查询不是真正的查询,真正的查询包含240列和240个值。

-我尝试按照这个例子进行交易:https://msdn.microsoft.com/en-us/library/86773566(v=vs.110).aspx

-sql变量是SqlConnection类型的。

感谢您的帮助。

【问题讨论】:

  • 一个重要的方面是每个插入都发生在它自己的事务中,并且为了到达 SQL Server 必须在向客户端确认之前验证它是否已写入磁盘。将这 2000 个插入包装在一个事务中,您应该会看到不同的数字。
  • 三个问题:sql是什么?您的 sql server 和应用程序之间的延迟是多少?与TSQL版本的15s相比,“长时间”是多长时间。老实说,即使在 TSQL 版本中,对于 2000 行,15 秒也是一个巨大时间 - 那台服务器是不是特别慢?
  • @JeroenMostert 虽然这是 true,但它并没有真正解释两个版本之间的区别,因为 TSQL 版本是 2000交易
  • 我怀疑除了 C# 和 SSMS 之外还有一些重要的环境差异。一方面,您每次都在 C# 中编写控制台行,而不是在 SSMS 中。
  • 还应该补充一下,你在SSMS中显示的查询真的不是这样做的方法。应该有一个插入,而不是 2000。它应该在一秒内运行,而不是 15 秒。

标签: c# sql-server ssms sqlcommand


【解决方案1】:

听起来您的 SQL 服务器和应用程序服务器之间存在很高的延迟。当我在本地执行此操作时,纯 TSQL 版本运行时间为 363 毫秒,而具有 2000 次往返的 C# 版本需要 1061 毫秒(因此:每次往返大约 0.53 毫秒)。注意:我把Console.WriteLine 拿走了,因为我不想衡量Console 的速度有多快!

对于 2000 个插入,这是一个相当公平的比较。如果你看到的东西大不相同,那么我怀疑:

  • 您的 SQL 服务器功能严重不足 - 在任何情况下(我的 363 毫秒计时已开启)它应该需要 15 秒(从问题中)插入 2000 行我的台式电脑,而不是快速服务器)
  • 如前所述;你有很高的延迟

请注意,还有一些诸如“DTC”之类的东西可能会根据连接字符串和环境事务 (TransactionScope) 影响性能,但我假设这些不是这里的因素。

如果您需要提高这里的性能,首先要做的是找出 为什么它如此糟糕 - 即原始服务器性能糟糕 ,并且延迟是巨大的。这些都不是编码问题:这些都是基础架构问题。

如果您无法解决这些问题,那么您可以围绕它们编写代码。表值参数或批量插入 (SqlBulkCopy) 都提供了传输多行的方法,而无需为每次执行支付往返费用。您还可以使用“MARS”(多个活动结果集)和流水线插入,但这是一个相当高级的主题(大多数人倾向于不建议启用 MARS)。

【讨论】:

  • 嗨@Marc,感谢您的回答,我正在使用托管在Microsoft Azure 中的SQL Server,互联网的加载速度为20 Mbits;查询可能很大,因为实际上列不是 4,列是 240。这会是问题吗?
  • “高延迟”与您的 Mbits 无关。如果您想消除延迟,请构建一个大型查询或批处理,而不是“啄木鸟”服务器,因为每次点击都会有新的延迟。
  • @AndresCamacho 20 Mbits 是带宽,而不是延迟;两个意义迥异的数字。一辆装满硬盘的 UPS 卡车具有难以置信的带宽和可怕的延迟。延迟是怎样的?
  • @AndresCamacho 说:是的,云主机因高延迟而臭名昭著,特别是如果您从 外部 同一个场连接到它 - 您的应用服务器和sql-server 在同一个位置?如果不是:光速在这里是一个真正的问题,你不能超过光速。
  • @MarcGravell 目前应用服务器是我的笔记本电脑,我不知道如何测量服务器的延迟
【解决方案2】:

确保尽量减少表上的索引数量并使用 SqlBulkCopy,如下所示

DataTable sourceData=new DataTable();
using (var sqlBulkCopy = new SqlBulkCopy(_connString))
{
    sqlBulkCopy .DestinationTableName = "DestinationTableName";
    sqlBulkCopy .WriteToServer(sourceData);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    相关资源
    最近更新 更多