以前有个同事学习非常广,新玩意啥都懂,什么Restful,什么MongoDB都玩过,还特能讲!顺着领导做事,非常得领导欢心!
不过有个问题,对性能一点感觉都没有,很容易写出一些炸弹代码!一运行就把SQL Server炸飞,性能急剧下降,timeout问题常出。
运行几个月问题也发现了,但是当时觉得可能就该这样,他也不知道他的代码不行,没有做数据库优化。
前几个月,退出公司到另外一家创业公司当CTO去了。用户经常抱怨timeout,更新不完整。
老板只好把我叫来,我只好啃他的炸弹代码!替他擦屁股!
就这样,我跟老板说他的代码不行,老板都帮他说话,帮他掩饰,说他的商业逻辑对的。
商业逻辑确实对,但是性能太差,运行表现太差,不是高手还找不出毛病。
下面简单的描述一下代码
using SqlConnection1{
open SqlConnection1;
using SqlCommand1 {
using SqlDataReader=SqlCommand1.executeCommand{
while(SqlDataReader.Read()){
foreach( dbColumn in DbColumns){
using SqlConnection2{
open SqlConnection;
using SqlCommand2 {
update table set fieldx=0 where name='a' and state='b';//根据表中每行每列的值更新某个表
}
}
}
}
}
}
}
问题1,不应该把一个循环调用的SQLcommand2嵌入在另一个SqlCommand1中,这样的话上面的SQLCommand1很容易扔出timeout异常,导致部分数据被更新。这是因为循环调用的SQLcommand2可能会执行很长时间。
解决办法是在SqlCommand1先把数据读入到内存中,例如DataTable,然后再循环读DataTable的每一个DataRow
using SQLConnection1{
open SQLConnection1;
using SQLCommand1 {
using SQLDataReader=SQLCommand1.executeCommand(){
fill DataTable1;(把数据一次读到DataTable1)
}
}
foreach (dataRow in DataTable1.Rows){
foreach( dbColumn in DbColumns){
using SQLCommand2 {
update table1 set fieldx=0 where name='a' and state='b';//根据表中每个列的值更新某个表
}
}
}
}
问题2,没有对table1对列name和state加一个index,表中有2万多行,DataTable1中大约有80行,80列,没运行一次要做80*80=6400个全表扫描,时间很长,所以数据库服务器性能急剧下降,一堆timeout异常抛出!可能单次运行上面的update table1感觉挺快,但是6400次就很恐怖了。