我刚从WinForms应用程序运行查询,该应用程序为2k记录更新1个字段,但通常会更多。唯一的问题是该应用程序只是停止响应,更新10条记录大约需要30秒,这还不够好。我怎么搞砸了?
代码
using (SqlConnection conx = GetConnection())
{
conx.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conx;
int counter = 0;
foreach (DataRow row in mainResultsTable.Rows)
{
if(controlResult)
{
thisSerial = row[2].ToString();
col = "[someColumn]";
}
cmd.CommandText = "UPDATE SomeTable$ SET [ToBeUpdated] = '" + DateTime.Now.ToString() + "' WHERE SomeColumn ='" + thisSerial.ToString() + "'";
cmd.ExecuteNonQuery();
counter++;
if (counter == 10)
{
MessageBox.Show("10");
}
}
}
}
PS。测试不是非常准确,我等待Messagebox弹出。
所以我最后做的是在SQL Server上创建一个临时表,导入上传数据并批量执行,在操作完成后删除临时表,这是否可取?
答案 0 :(得分:3)
如果可能,您可以更好地运行一个SQL调用来更新所有记录,这将显着加快。如果您可以使用参数定义执行此操作的查询,则应该令人满意地更新。
或者,您必须考虑是否可以进行此操作,具体取决于您是否需要在完成之前完成此操作。
答案 1 :(得分:3)
我可以做一些事情,但最重要的是:
检查数据库服务器是否正常。也许某些进程停留在100%的处理器时间,并且您的数据库速度变慢。
检查数据库是否有锁。发布10个更新的时间不应超过几分之一秒,除非表的数量大约为数十亿。
检查表是否由SomeColumn
列编入索引。这可以大大提高性能。
尝试从SQL Studio运行相同的10个语句,看看它们需要多长时间,以隔离问题的一面(客户端代码/数据库服务器)
尝试发送更少的更新语句,如果mainResultsTable
有1.000.000行,您将发送1.000.000更新语句。如果使用SQL Server 2008,则可以使用带table-valued parameters的存储过程,否则,可以编译XML parameter,然后在服务器上解析它。您也可以使用Peter响应中的IN
子句技巧,但我宁愿使用TVP或XML
尝试执行Application.DoEvents()
以保持用户界面的响应能力(这通常是错误的方法,但它有时会快速有效地修复)
使用BackgroundWorker
将整个更新过程转换为另一个帖子。
除此之外,如果thisSerial
属性为varchar
,则此代码可能对二阶SQL注入开放。
答案 2 :(得分:2)
将所有连续出版物提取到列表中:
var serials = new List<string>();
foreach (DataRow row in mainResultsTable.Rows)
serials.Add(row[2].ToString());
使用一个SQL查询更新所有行:
"UPDATE SomeTable SET [ToBeUpdated] = '" + DateTime.Now.ToString() + "' WHERE SomeColumn IN ('" + String.Join("','", serials) + "')";
答案 3 :(得分:1)
您必须拥有someColumn
的索引。否则,UPDATE必须端到端扫描表以查找需要更新的行。
但是,接近在客户端逐个更新2k行并单独应用每个更新的问题从根本上是有缺陷的。这一次,它将是不成功的。但更重要的可能是不正确的。您正在更新的行是“实时”,并在您查看它们后进行更改。在服务器端将更新作为单个集合导向操作更好。如何做到这一点取决于我们无法猜测的一些因素只是看你的帖子。我建议你阅读Table-Valued Parameters in SQL Server 2008。