SqlCommand的CommandText的长度是否有所不同?我也不是在谈论成千上万的角色.这就是我所拥有的:
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
for (int i=0; i<1000; ++i)
{
string name = i.ToString() + "Bob" + i.ToString();
string email = i.ToString() + "Jim" + i.ToString();
// etc...
cmd.Parameters.Clear();
cmd.Parameters.Add(new SqlParameter("@name", name));
cmd.Parameters.Add(new SqlParameter("@country", country));
DateTime cmdStart = DateTime.Now;
cmd.ExecuteNonQuery();
DateTime cmdEnd = DateTime.Now;
TimeSpan len = cmdEnd - cmdStart;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用以下sql,第一次迭代需要0.5秒.第二个需要1.1秒.第三个需要3.3秒.等等,直到它只是暂停超时.
string sql =
"INSERT INTO Test " +
" ([name] " +
" ,[email] " +
" ,[country] " +
" ,[comment] " +
" ,[date] " +
" ,[key_v0] " +
" ,[key_v1] " +
" ,[expires_v1] " +
" ,[expires_v2] " +
" ) " +
" VALUES " +
" (@name " +
" ,@email " +
" ,@country " +
" ,' ' " +
" ,@date " +
" ,@key_v0 " +
" ,@key_v1 " +
" ,@expires_v1 " +
" ,@expires_v2 " +
" )";
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用以下sql,整个循环将在一秒钟内执行.
string sql =
"INSERT INTO Test " +
"([name] " +
",[email] " +
",[country] " +
",[comment] " +
",[date] " +
",[key_v0] " +
",[key_v1] " +
",[expires_v1] " +
",[expires_v2] " +
") " +
"VALUES " +
"(@name " +
",@email " +
",@country " +
",' ' " +
",@date " +
",@key_v0 " +
",@key_v1 " +
",@expires_v1 " +
",@expires_v2 " +
")";
Run Code Online (Sandbox Code Playgroud)
唯一的区别是空白.删除空格会使总字符数从428增加到203.除了引用4k和8k限制外,我无法找到任何引用CommandText长度的内容.我离它不远了.
我已经运行了两个版本,并且所有调用的持续时间都低于10毫秒.从SQL引擎内部完成命令直到ExecuteNonQuery返回时,似乎发生了延迟.
我知道有其他方法可以做到这一点.我不是在问更好的方法.我在问减速的来源.
更新:作为测试,我在查询的末尾添加了空格.一旦我超过400个字符总数,它就会放慢速度.有趣的是,在414个字符中,前99个插入速度很快.在415个字符处,前9个插入是快速的.因为我根据迭代次数改变了一些字符串,所以这有点意义.例如,第10次插入比第9次插入略长,第100次插入比第99次插入略长.
虽然我有点理解更长的插入需要更长时间,但我无法理解快速和慢速之间的明显区分以及差异的绝对大小.我也不明白为什么花费的时间会增加.
更新2 :(回应Peter Oehlert回答的附加信息):整个数据库都很干净.没有其他表,并且每次运行都会删除并重新创建测试表.没有索引,触发器或外键.有一个'id'列是主键.
这是从专门用于解决此问题的控制台应用程序中提取的代码.它只包含重现此行为的必要代码.
(Aditional profiler信息):运行SQL事件探查器时,有一个名为TextData的列显示命令和数据.一个例子是:
exec sp_executesql N'INSERT INTO Test ([name] ,[email] ,[country] ,[comment] ,[date] ,[key_v0] ,[key_v1] ,[expires_v1] ,[expires_v2] ) VALUES (@name ,@email ,@country ,'' '' ,@date ,@key_v0 ,@key_v1 ,@expires_v1 ,@expires_v2 ) ',N'@name nvarchar(4),@country nvarchar(2),@email nvarchar(3),@date datetime,@key_v0 nvarchar(4000),@key_v1 nvarchar(4000),@expires_v1 datetime,@expires_v2 datetime',@name=N'9Bob',@country=N'us',@email=N'Jim',@date='2009-08-28 15:35:36.5770000',@key_v0=N'',@key_v1=N'',@expires_v1='2009-08-28 15:35:36.5770000',@expires_v2='2009-08-28 15:35:36.5770000'
Run Code Online (Sandbox Code Playgroud)
该行长796个字符并且运行速度很快.将名称从"9Bob"更改为"10Bob"会导致插入缓慢.796和797都不是一个重要的数字.删除exec sp_executesql部分意味着长度为777和778.它们似乎也不重要.
我很难过.
更新:发布跟踪:http://www.jere.us/WierdInserts.trc
好吧,我没有直接的答案,但这是我解决这个问题的方法。
SQL
如果是数据库,那么我会看一些事情:每个人都在喋喋不休地讨论字符串连接问题,虽然这是真的,但很可能会占用你不到 5 毫秒的时间。我也认为这些空间是问题的根源。同样,它会产生很小的差异,但不会解释您所描述的退化。您正在寻找具有这种级数(0.5、1.1、3.3)的东西。
我会特别查看您在此表上定义的索引、该表上有哪些约束/触发器以及存在多少外键关系。此外,我会拉出执行缓慢的查询并在查询管理器(sql 企业管理器)中运行它们。
我可能调查的最后一件事是是否存在错误的缓存计划,从而引入了某些数据相关功能的问题。仅当您有一些有趣的触发器使用您的数据或某些类型的索引更新时,这才有效。您可以通过在调用插入语句之间调用 DBCC FREEPROCCACHE 来查看这一点,看看它是否有区别。此命令将清除计划缓存,强制 sql 为查询重新生成新的执行计划。
客户
如果是客户端,那么您需要确定代码中导致问题的原因。如果您有一个性能跟踪工具(例如 Visual Studio 性能分析器)可以检测您的代码,我会使用它,因为它会非常快速地告诉您到底是什么占用了这么多时间。
如果您没有该选项,那么首先将代码提取到一个新的控制台应用程序中,并尽可能减少意外情况,看看是否可以重现该行为。您正在寻找可能导致您所看到的进展的原因。
归档时间: |
|
查看次数: |
3934 次 |
最近记录: |