2011年6月3日 星期五

DataTable 的各種查詢方式效能比較

由於 DataTable.Rows.Find 只提供對 PrimaryKey 的查詢能力,
如果不是 PrimaryKey 的話,
似乎只能用 DataTable.Select ,
說明文件裡面說"取得符合按照主索引鍵順序 (如果沒有,則使用加法順序) 的篩選準則的所有 DataRow 物件之陣列。",
看來如果查詢的欄位不是 PrimaryKey 的話就會用 Table scan 的方式去查資料;
上網找到一份資料 【使用 ADO.NET 的最佳經驗分享-更多有用秘訣】 ,
裡面的"在資料中找尋資料"這一段裡面提到, 
查詢的欄位是主索引鍵的話就用 DataTable.Rows.Find 不要用 DataTable.Select ,
非主索引鍵的話就建立 DataView 來增加多重查詢的效能;
然後我記得再查詢相關說明的時候,
微軟又建議我們用 Linq to DataSet 的方式來查詢!!!
也許年代不同有不同的方式可以得到更好的效能吧?
所以我決定把我所想得到的查詢方式通通拿來測試一下效能,
所以才會有今天這一篇文章。
我所想到的方法有下列幾項:
  1. DataTable.Rows.Find
  2. DataTable.Select
  3. Linq
  4. DataView
  5. Dictionary
這五種方式來查詢。
除了第一種方式是用 PrimaryKey 的欄位來查詢之外,
其他的四種方式都不是用 PrimaryKey 的欄位來查詢。

測試的 Table 是一個六千多筆的 Table ,
測試的機器是 vaio vpcsb-16 、 vs2008 ;
為了公平考量,
每次查詢前都會複製要查詢的 DataTable 到暫存的 DataTable ,
然後用暫存的 DataTable 來查詢;
測試的結果如下;


Begin=======================================
Start create ObjectObject create time : 1408ms


 3ms : byFind PK1 <=第一次用 PrimaryKey 查詢所花的時間
 0ms : byFind PK2 <=第二次用 PrimaryKey 查詢所花的時間,第二次以後都是花費 0ms ,可能是有把 index table cache 在記憶體中的關係!(個人瞎猜)
 16ms : bySelect nonPK1 
 17ms : bySelect nonPK2 <= Select 每一次查詢所花費的時間看起來差不多,可見真的是 Table scan
 2ms : byLinq nonPK1 
 1ms : byLinq nonPK2 
 0ms : byLinq nonPK3 <= Linq 平均下來每次所花費的時間大概都是 1ms
 25ms : byDataView1st nonPK1 <= 這是包含建立 DataView 的時間
 0ms : byDataView2nd nonPK2 <= 第二次查詢就快多了
 2ms : byDictionary1st nonPK1 <= 這是包含建立 Dictionary 的時間
 0ms : byDictionary2nd nonPK2 <= 第二次查詢就快多了
End=======================================


【測試結果說明】
DataTable.Rows.Find:看起來如果要查的欄位是 PrimaryKey 的話用 DataTable.Rows.Find 是比較快、也比較方便的。
DataTable.Select:用起來雖然方便,但是效能看起來是最差的。
Linq:看起來也不慢,寫起來也不會太難,是可以考慮拿來使用,而且相對於 DataView & Dictionary 也不需要有事前的準備。
DataView:第一次需要建立的時間花費太多,但是第二次以後看起來是比 Linq 快。
Dictionary:我是用 Dictionary<string, DataRow> 很暴力的方式處理,不過看起來建立的時間比 DataView 快很多,第二次以後的查詢也很快,如果對效能很要求的話或許可以考慮用這個方是。


也許應該用更多的資料來測試,
但是目前找不到更多資料的 Table 了,
也許找個幾百萬筆資料的 Table 應該可以更分出高下;
目前尚未考量記憶體的使用量,
主要原因也是因為我不知道該怎麼去測是記憶體的使用量啦!
【結論】
基於以上幾種測試的結果,
我選擇了如果是查詢 PrimaryKey 的話就用 DataTable.Rows.Find ,不然就先用 Linq
如果有其他效能的考量的話就遇到的時候再看著辦囉!

沒有留言:

張貼留言