最近老大對我們做的資料匯入功能意見挺大,資料量一上來,匯入時間就很長,嚴重影響使用者體驗。因此,不得不花時間搗鼓了一下資料匯入的效能優化問題

原始程式碼:

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();
}

我忐忑不安地點開“除錯”。。。。竟然成功了!!!

 

總結:

其實沒啥好總結的,就是一句話:批量處理用事務!