[ASP.NET] Dictionary 與 DataTable Performance 實驗

  • 8166
  • 0

[ASP.NET] Dictionary 與 DataTable Performance 實驗

在一個討論的場合裡,談到了有關某個問題的解決方法,有習慣用DataTable解也有習慣用Dictionary來解,當然也有其它方式可以解,不過本文並不在討論該問題最佳解法是什麼,而是以DataTable及Dictionary來做個小實驗。

 

實驗情境:

假設程式裡希望能先把一些資料暫存起來,供後續程式邏輯來運用,而其中涉及了必須從這先前暫存的資料堆中來找到符合條件某些資料的運用,採DataTable有二個方法可以做到,一個是Select()方法,一個是具PrimaryKey的Rows.Find()方法,而採用Dictionary的話,則是以Key來找資料,筆者分別假設以500、1000、5000、10000、5000的資料量取其中一筆來實驗看看。

 

  • 測試含相關物件建立及填充資料的過程(單位:毫秒)

【Dictionary】

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();

Dictionary<string, string> dic = new Dictionary<string, string>();

for (int i = 0; i < cnt; i++)
{
	dic.Add(i.ToString(), i.ToString());
}

this.TextBox1.Text = dic["100"].ToString();
sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【DataTable.Select】

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();

DataTable table = new DataTable();
DataColumn column;

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "key";
table.Columns.Add(column);

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "val";
table.Columns.Add(column);

for (int i = 0; i < cnt; i++)
{
	table.Rows.Add(i.ToString(), i.ToString());
}

DataRow[] dr = table.Select("key='100'");
this.TextBox1.Text = dr[0]["val"].ToString();

sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【DataTable.Rows.Find】

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();

DataTable table = new DataTable();
DataColumn[] keys = new DataColumn[1];
DataColumn column;

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "key";
keys[0] = column;
table.Columns.Add(column);

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "val";
table.Columns.Add(column);

table.PrimaryKey = keys;

for (int i = 0; i < cnt; i++)
{
	table.Rows.Add(i.ToString(), i.ToString());
}

string keystr = "100";
DataRow dr = table.Rows.Find(keystr);
this.TextBox1.Text = dr["val"].ToString();

sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【測試結果】

image

 

image

 

  • 僅測試計算找資料的過程(單位:毫秒)

【Dictionary】

Dictionary<string, string> dic = new Dictionary<string, string>();

for (int i = 0; i < cnt; i++)
{
	dic.Add(i.ToString(), i.ToString());
}

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
this.TextBox1.Text = dic["100"].ToString();
sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【DataTable.Select】

DataTable table = new DataTable();
DataColumn column;

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "key";
table.Columns.Add(column);

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "val";
table.Columns.Add(column);

for (int i = 0; i < cnt; i++)
{
	table.Rows.Add(i.ToString(), i.ToString());
}

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
DataRow[] dr = table.Select("key='100'");
this.TextBox1.Text = dr[0]["val"].ToString();

sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【DataTable.Rows.Find】

DataTable table = new DataTable();
DataColumn[] keys = new DataColumn[1];
DataColumn column;

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "key";
keys[0] = column;
table.Columns.Add(column);

column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "val";
table.Columns.Add(column);

table.PrimaryKey = keys;

for (int i = 0; i < cnt; i++)
{
	table.Rows.Add(i.ToString(), i.ToString());
}

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
string keystr = "100";
DataRow dr = table.Rows.Find(keystr);
this.TextBox1.Text = dr["val"].ToString();

sw.Stop();
this.Label1.Text = sw.Elapsed.TotalMilliseconds.ToString();

 

【測試結果】

image

image

 

  • 討論

(1) 單就從資料堆中找尋特定資料這件事((實驗二)而言Dictionary的performance是比較穩定的,無論資料量多或少,同樣的具有PrimaryKey的DataTable.Rows.Find()也呈現相同的情況,二者之間從數據來看Dictionary更快一些,相對的DataTable.Select()方法,則受資料量的影響,無法保有一定的穩定效能,數量愈大效能顯然愈差,從10000筆資料到50000筆資料,數據急速升高,可以看到這樣的一個現象。

(2) 但若把整個物件建立的過程及相關屬性的設定納入考量時(實驗一),可以發現Dictionary相較於其它二種方式仍保有優勢也保持穩定的數據趨勢,但有趣的是建立PrimaryKey的方式反而比不建立PrimaryKey數據上來的差,這應該與建立PrimaryKey所花費的成本有關。

(3) 以上實驗無法斷定在任何需求下Dictionary的做法一定優於DataTable,特別是若還要對資料堆進行增、修、刪的情況下,以及資料面是否涉及到物件等,更複點的需求可能還有多維資料結構等,因此以上僅單就取得單一資料做簡單的測試實驗,僅能說明在本實驗相同情況下Dictionary的做法優於DataTable,建議運用上仍需視需求做考量。

 

若本文對您有所幫助,歡迎轉貼,但請在加註【轉貼】及來源出處,並在附上本篇的超連結,感恩您的配合囉。

By No.18