【发布时间】:2016-06-30 01:15:42
【问题描述】:
概述
这个问题是这个问题的更具体的版本:
但我注意到其他数据类型的性能同样受到影响(事实上,就我而言,我根本没有使用任何 bigint 类型)。
这里有一些其他问题,似乎应该涵盖这个问题的答案,但我观察到的与他们所指出的相反:
- c# - When should "SqlDbType" and "size" be used when adding SqlCommand Parameters? - Stack Overflow
- .net - What's the best method to pass parameters to SQLCommand? - Stack Overflow
上下文
我有一些用于将数据插入表的 C# 代码。代码本身是数据驱动的,因为其他一些数据指定了应该插入数据的目标表。所以,虽然我可以在存储过程中使用动态 SQL,但我选择在我的 C# 应用程序中生成动态 SQL。
我插入的行的命令文本总是相同的,所以我在插入任何行之前生成一次。命令文本的格式为:
INSERT SomeSchema.TargetTable ( Column1, Column2, Column3, ... )
VALUES ( SomeConstant, @p0, @p1, ... );
对于每个插入,我创建一个 SqlParameter 对象数组。
对于 'nvarchar' 行为,我只是使用 SqlParameter(string parameterName, object value) 构造方法,并没有显式设置任何其他属性。
对于“退化”行为,我使用了 SqlParameter(string parameterName, SqlDbType dbType) 构造函数方法,并根据需要设置了 Size、Precision 和 Scale 属性。
对于这两个版本的代码,传递给构造函数方法或单独分配给Value 属性的值的类型为object。
代码的“nvarchar”版本大约需要 1-1.5 分钟。 “退化”或“特定类型”代码耗时超过 9 分钟;所以慢了 6-9 倍。
SQL Server Profiler 没有发现任何明显的罪魁祸首。特定于类型的代码正在生成看起来更好的 SQL,即动态 SQL 命令,其参数包含适当的数据类型和类型信息。
假设
我怀疑,因为我将 object 类型值作为参数值传递,ADO.NET SQL Server 客户端代码在生成命令并将命令发送到 SQL Server 之前正在强制转换、转换或以其他方式验证该值.我很惊讶从 nvarchar 到 SQL Server 必须执行的每个相关目标表列类型的转换比客户端代码执行的任何操作都快得多。
注意事项
我知道SqlBulkCopy 可能是插入大量行的最佳选择,但我更好奇为什么“nvarchar”的情况优于“特定类型”的情况,并且考虑到它通常处理的数据量,我当前的代码足够快。
【问题讨论】:
-
您是否还比较了此类半散装刀片的性能?
INSERT SomeSchema.TargetTable ( Column1, Column2, Column3, ... ) values ( SomeConstant, @p0, @p1, ... ), ( SomeConstant, @p0, @p1, ... ), ( SomeConstant, @p0, @p1, ... ), ( SomeConstant, @p0, @p1, ... );就我个人而言,我注意到最好的性能是一次 500kb 到 800kb 的块。 -
@Ralph 我没有。这是一个有趣且好主意,但对我来说实施起来将是一项不平凡的工作。我的代码需要处理跨越相当大“宽度”范围的现有表,即一些表只包含几列,而另一些表包含 200 多列。我想我只是硬着头皮使用
SqlBulkCopy和自定义IDataReader实现,这样我就可以{ semi-bulk / chunk } 从我的来源插入“流式传输”数据。 -
使用分析器查看哪些特定区域需要更长时间。
-
@MartinSmith 这是一个很好的建议。 Visual Studio 性能探查器似乎表明我的插入方法中的某些 LINQ 扩展方法明显较慢。更换扩展方法后,特定类型的代码在不到 2 分钟的时间内完成。它仍然慢了 30-40%,但我生成参数的代码似乎很可能是罪魁祸首。
-
“从 nvarchar 转换为每个相关的目标表列类型”是什么意思?你真的应该为 NVARCHAR 东西设置最大大小。此外,传递没有直接映射的数据类型也会影响性能:object/SQL_VARIANT、DATETIME(而不是 DATETIME2)、DECIMAL、Guid/UNIQUEIDENTIFIER 等。
标签: c# sql-server