衆所周知,Sqlite是一個輕量級的數據庫,僅僅須要一個exe文件就能運行起來。在處理本地數據上,我比較喜歡選擇使用它,不只是由於他與sql server有着比較相近的語法,還由於它不須要安裝,僅須要經過命令行就能啓動了,並且他在處理大數據時,性能比sql server好不少,好吧這裏不繼續爭論性能優劣。sql
首先,此次的問題是在一次項目中遇到的,項目要求能大量導入數據,並且因爲項目性質(輕便,本地化),因此我選擇sqlite來存放數據。數據庫
初版代碼:緩存
1 StringBuilder sql = new StringBuilder(); 2 foreach (DataRow dr in dt.Rows) 3 { 4 sql.Append("INSERT INTO Info (Name,Code) VALUES('"+dr[0]+"','"+dr[1]+"') \r\n"); 5 } 6 sqlHelper.SqliteHelper.ExecuteNonQuery( sql.ToString(), CommandType.Text);
從上面的代碼看來,我沒有進行任何優化工做,我用這種方式插入了1萬條數據用了1分多鐘,可見優化的重要性(百萬級數據跑起來...不敢想象)。ide
開啓事務:性能
1 StringBuilder sql = new StringBuilder(); 2 sql.Append("BEGIN;");//開啓事務 3 foreach (DataRow dr in dt.Rows) 4 { 5 sql.Append("INSERT INTO Info (Name,Code) VALUES('"+dr[0]+"','"+dr[1]+"') \r\n"); 6 } 7 sql.Append("COMMIT;");//提交事務 8 sqlHelper.SqliteHelper.ExecuteNonQuery( sql.ToString(), CommandType.Text);
因爲sqlite的數據操做實質上是對於其數據文件的IO操做,頻繁的插入數據會致使文件IO常常開閉,很是損耗性能能。事務做用即是使數據先緩存在系統中,提交事務時便提交全部的更改到數據文件,此時數據文件的IO只須要開閉一次,且避免了長期佔用文件IO所致使性能低下的問題。此時,開啓事務處理後性能上雖然有了大幅度的提高,可是結果仍舊不理想,哪還有什麼在影響着性能呢?下面嘗試開啓預處理來解決問題。大數據
開啓預處理:優化
1 public static int ExecuteNonQuery(string commandText, CommandType commandType) 2 { 3 int result = 0; 4 if (commandText == null || commandText.Length == 0) 5 throw new ArgumentNullException("sql語句爲空"); 6 using (SQLiteConnection con = new SQLiteConnection(connectionString)) 7 { 8 SQLiteCommand cmd = new SQLiteCommand(); 9 cmd.Connection = con; 10 cmd.CommandText = commandText; 11 cmd.Prepare();//開啓預處理 12 try 13 { 14 result = cmd.ExecuteNonQuery(); 15 } 16 catch (Exception ex) 17 { 18 throw ex; 19 } 20 } 21 return result; 22 } 23
預處理的原理就是將一條語句先預編譯到數據庫,下次再次執行相同的語句時,就不用再次編譯,節省了大量的時間。由此看來,代碼彷佛尚未優化完成。就初版代碼來講,因爲批量插入的數據不盡相同,因此數據庫會屢次編譯插入語句,性能會損耗很是多,也就形成插入須要的時間會比較多。有沒有一條語句是能夠循環使用的?答案是有的,使用參數化傳值,就能使每一次的插入的sql語句都是相同的。ui
參數化(數據庫幫助類那邊我就不寫了):spa
1 StringBuilder sql = new StringBuilder(); 2 SQLiteParameter[] sp = new SQLiteParameter[2]; 3 foreach (DataRow dr in dt.Rows) 4 { 5 sql.Clear(); 6 sql.Append("INSERT INTO Info (Name,Code) VALUES(@Name,@Code) \r\n"); 7 sps[0] = new SQLiteParameter("@p1", dr["Name"]); 8 sps[1] = new SQLiteParameter("@p2", dr["Code"]); 9 sqlHelper.SqliteHelper.ExecuteNonQuery(sql.ToString(),sp, CommandType.Text); 10 }
通過一系列優化處理後,插入1萬條數據只須要不到1秒,性能獲得了極大的提高。命令行
另外,本人新手,若有不對,望不吝指教。