最近老大对我们做的数据导入功能意见挺大,数据量一上来,导入时间就很长,严重影响用户体验。因此,不得不花时间捣鼓了一下数据导入的性能优化问题
原始代码:
MySqlCommand command = new MySqlCommand();
command.Connection = conn;
using (StreamReader sr = new StreamReader(new FileStream(sqlFileName, FileMode.Open, FileAccess.Read)))
{
while(sr.Peek() !=-1)
{
string line = sr.ReadLine();
if(line.StartsWith("insert"))//目前只处理insert语句
{
command.CommandText = line;
command.ExecuteNoQuery();
}
}
}
当然,这个代码性能有很大的问题,所以我略施小计形成了第二版代码:
MySqlCommand command = new MySqlCommand();
command.Connection = conn;
List<string> fileLines = new List<string>();
using (StreamReader sr = new StreamReader(new FileStream(sqlFileName, FileMode.Open, FileAccess.Read)))
{
while(sr.Peek() !=-1)
{
string line = sr.ReadLine();
fileLines.Add(line);
}
foreach(string line in fileLines)
{
if(line.StartsWith("insert"))//目前只处理insert语句
{
command.CommandText = line;
command.ExecuteNoQuery();
}
}
}
这一版代码将文件的每一行先存到list变量里面,然后再遍历list变量进行插入操作,避免因为执行sql语句而延误文件读写
我兴致勃勃的点开了“调试”,结果大失所望,像第一版代码一样慢如狗。。。。
好吧,我又开始了艰辛的探索之旅,经过很长时间的奋战,终于形成了第三版代码:
MySqlCommand command = new MySqlCommand();
command.Connection = conn;
List<string> fileLines = new List<string>();
using (StreamReader sr = new StreamReader(new FileStream(sqlFileName, FileMode.Open, FileAccess.Read)))
{
while(sr.Peek() !=-1)
{
string line = sr.ReadLine();
fileLines.Add(line);
}
MySqlTransaction trans = conn.BeginTransaction();
foreach(string line in fileLines)
{
if(line.StartsWith("insert"))//目前只处理insert语句
{
command.Transaction = trans;
command.CommandText = line;
command.ExecuteNoQuery();
}
}
trans.Commit();
}
我忐忑不安地点开“调试”。。。。竟然成功了!!!
总结:
其实没啥好总结的,就是一句话:批量处理用事务!