DataTable新增資料之效率問題
最近讀到一篇不錯的文章,
內容是在說使用DataTable新增資料,怎樣才會快
[原文
](http://marlon.blog.ithome.com.tw/post/894/70698)此外,原作者還有很多不錯的文章,大家可以去看看。
我引用了這篇原文,順便加上些自己的看法與註解。
DataTable 新增資料,這麼簡單的問題有誰不會?但是您用對方法了嗎?如果是新增一筆資料給使用者輸入,用什麼方法沒有太大的差別,但如果是用程式碼大量新增資料,不同的方法時間可以差上數倍,欄位越多越明顯,廢話不多說,直接看不同的寫法測試數據
測試 20 個字串欄位及 20 個整數欄位, 無 Constraints, 新增 10000 筆資料,
每種方法測試10次, 去除最大及最小值後分列列出其餘8次中 (最小值, 平均值, 最大值), 單位 Milliseconds
( 有興趣者可測試有 Constraints 時方法一與方法二的差異 )
方法一 ( 405.6, 416.0, 426.4 )
DataRow row; for (int rowIndex = 1; rowIndex <= RowCount; rowIndex++) { row = table.NewRow(); for (int i = 1; i <= ColCount; i++) { row["ColString" + i.ToString()] = string.Concat(rowIndex.ToString(), ".", i.ToString()); row["ColInt" + i.ToString()] = rowIndex * 1000 + i; } table.Rows.Add(row); }
SanC : 這是我們最常用的方法,在撰寫時,算是最直覺的寫法。
方法二 ( 390.0, 395.9, 405.6 )
DataRow row; table.BeginLoadData(); for (int rowIndex = 1; rowIndex <= RowCount; rowIndex++) { row = table.NewRow(); for (int i = 1; i <= ColCount; i++) { row["ColString" + i.ToString()] = string.Concat(rowIndex.ToString(), ".", i.ToString()); row["ColInt" + i.ToString()] = rowIndex * 1000 + i; } table.Rows.Add(row); } table.EndLoadData();
SanC:
這個方法修正了方法一的地方,
最顯著的是將使用table.BeginLoadData()和table.EndloadData()放在最外圈,
我的猜測,再沒寫這兩個Function時,當執行10000次時,也同時呼叫了10000次的這兩個function
所以,速度也慢了。
方法三 ( 234.0, 245.1, 254.8 )
int[] strColIndex = new int[ColCount]; int[] intColIndex = new int[ColCount]; for (int i = 1; i <= ColCount; i++) { strColIndex[i - 1] = table.Columns["ColString" + i.ToString()].Ordinal; intColIndex[i - 1] = table.Columns["ColInt" + i.ToString()].Ordinal; } DataRow row; table.BeginLoadData(); for (int rowIndex = 1; rowIndex <= RowCount; rowIndex++) { row = table.NewRow(); for (int i = 1; i <= ColCount; i++) { row[strColIndex[i - 1]] = string.Concat(rowIndex.ToString(), ".", i.ToString()); row[intColIndex[i - 1]] = rowIndex * 1000 + i; } table.Rows.Add(row); } table.EndLoadData();
SanC:
這裡使用陣列strColIndex和intColIndex來存欄位名稱的編號
( 例如: 欄位名稱ColSting1的編號為1 ColString2的編號為2 )
此陣列就是來存取此值,
然後在新增資料的時候,使用的不是用字串當索引
( 字串當索引 row["ColString1"] )
而是使用數字( 編號 )當索引,在不經過查詢(轉換)的過程,
使得速度更快了。
方法四 ( 119.6, 127.4, 135.2 ) - 較佳寫法, 使用 object[] 新增資料
int[] strColIndex = new int[ColCount]; int[] intColIndex = new int[ColCount]; for (int i = 1; i <= ColCount; i++) { strColIndex[i-1] = table.Columns["ColString" + i.ToString()].Ordinal; intColIndex[i-1] = table.Columns["ColInt" + i.ToString()].Ordinal; } object[] itemArray; table.BeginLoadData(); for (int rowIndex = 1; rowIndex <= RowCount; rowIndex++) { itemArray = new object[table.Columns.Count]; for (int i = 1; i <= 10; i++) { itemArray[strColIndex[i-1]] = string.Concat(rowIndex.ToString(), ".", i.ToString()); itemArray[intColIndex[i-1]] = rowIndex * 1000 + i; } table.Rows.Add(itemArray); } table.EndLoadData();
SanC:
又更加的改進,這裡使用object來做處理,而非使用DataRow來新增,
先建立一個名為 itemArray的object陣列
然後再將每個資料塞到陣列裡的每個物件裡,
然後再用table.Rows.Add(itemArray)來新增所有資料
這是最快的處理方法,至於為何,只能猜測因為object型別最單純!?
或是中間不需要經過轉換的過程。