Does CommandText SqlCommand Mean Length? I'm not talking about thousands of characters either. Here is what I have:
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; }
If I use the following sql, the first iteration takes 0.5 seconds. The second takes 1.1 seconds. The third takes 3.3 seconds. And so on, until he just throws a timeout.
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 " + " )";
However, if I use the following sql, the whole loop runs in a second.
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 " + ")";
The only difference is a space. Removing the space led to a total number of characters from 428 to 203. I could not find anything referring to the length of the CommandText, except for references to the limits of 4k and 8k. I'm nowhere near
I launched both versions with the launch of the profiler, and for all calls the duration is less than 10 ms. The delay seems to occur when the command completes inside the SQL engine until ExecuteNonQuery returns.
I know that there are alternative ways to do this. I am not asking about the best ways to do this. I ask about the source of the slowdown.
UPDATE: As a test, I added spaces to the end of the query. As soon as I received more than 400 characters, it slowed down. Interestingly, with 414 characters, the first 99 inserts are fast. With 415 characters, the first 9 inserts are fast. Since I am modifying some lines based on the number of iterations, this kind of makes sense. for example, the 10th insert is slightly longer than the ninth, and the 100th insert is slightly longer than the 99th.
As long as I understand that longer inserts should take longer, I cannot understand the clear distinction between fast and slow and the absolute value of the difference. I also do not understand why time is increasing.
UPDATE 2: (More info in response to Peter Oelert's answer): The entire database is clean. There are no other tables, and the test table is discarded and recreated for each run. No indexes, triggers or foreign keys. There is an id column, which is the primary key.
This is code extracted from a console application written specifically to fix this problem. It contains only the necessary code to reproduce this behavior.
(Additional profiler information): When starting the SQL profiler, there is a column called TextData that shows what the command and data are. Example:
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'
This string is 796 characters long and is fast. Changing the name from "9Bob" to "10Bob" results in a slow insertion. Neither 796 nor 797 seem significant. Removing the exec fragment sp_executesql means the lengths are 777 and 778. They also do not seem significant.
I'm at a dead end.
Update: Added here: http://www.jere.us/WierdInserts.trc