以文本方式查看主题 - Foxtable(狐表) (http://foxtable.com/bbs/index.asp) -- 专家坐堂 (http://foxtable.com/bbs/list.asp?boardid=2) ---- 令人目瞪口呆的效率差别(有修正) (http://foxtable.com/bbs/dispbbs.asp?boardid=2&id=8781) |
||||
-- 作者:狐狸爸爸 -- 发布时间:2010/12/7 12:36:00 -- 令人目瞪口呆的效率差别(有修正) 今天一个用户,希望在第三列中标出第一列有而第二列无的数据,假定第一列和第二列为整数型:
测试文件,注意每次测试都重新打开项目,不要保存:
我给出的代码为:
For Each dr As DataRow In DataTables("表A").DataRowsIf DataTables("表A").Find("第二列 = " & dr("第一列") ) Is Nothing Then dr("第三列") = True Else dr("第三列") = False End If Next 在数据为1万行,第三列无数据的时候,执行上述代码花费了整整234秒,显然这样的效率是让人难以接受的。
测试查询的代码:
Dim v As BooleanFor Each dr As DataRow In DataTables("表A").DataRows If DataTables("表A").Find("第二列 = " & dr("第一列")) Is Nothing Then v = dr("第三列") End If Next 测试赋值的代码:
For Each dr As DataRow In DataTables("表A").DataRowsdr("第三列") = True Next 出人意料的是,两段代码运行得都非常快,都在瞬间完成了。
Dim lst1 As New List(of DataRow)Dim lst2 AS New List(of DataRow) For Each dr As DataRow In DataTables("表A").DataRows If DataTables("表A").Find("第二列 = " & dr("第一列")) Is Nothing Then lst1.Add(dr) Else lst2.Add(dr) End If Next For Each dr As DataRow In lst1 dr("第三列") = True Next For Each dr As DataRow In lst2 dr("第三列") = False Next
同样在数据为1万行,第三列无数据的时候,执行上述代码只花了0.8秒,比原来的234秒快了整整300倍,效率差距之大,让人目瞪口呆。 原因应该找到了,为了验证我的想法,我另外写了两段代码测试,这次不使用Find进行查询,而是用Compute进行计算:
常规的代码,计算和赋值在同一个遍历语句:
Dim v As DoubleFor Each dr As DataRow In DataTables("表A").DataRows v = DataTables("表A").Compute("Count(第二列 )", "第二列 = " & dr("第一列")) dr("第四列") = v Next 估计应该更加高效的代码,计算和赋值分开进行:
Dim Dic As new Dictionary(of DataRow, Integer)Dim v As Double For Each dr As DataRow In DataTables("表A").DataRows v = DataTables("表A").Compute("Count(第二列 )", "第二列 = " & dr("第一列")) dic.Add(dr, v) Next For Each dr As DataRow In dic.Keys dr("第四列") = dic(dr) Next 果不其然,经过测试,第二段比第一段快了整整300倍。
现在我总结一下,符合以下三个条件,可能会出现效率低下的情况:
1、用For语句遍历某个表
强调一下,上述三项中提到的表必须都是同一个表。 我们改写的代码之所有高效,是因为改写后的代码2、3不再出现在同一个遍历语句中,而是在不同的遍历语句中出现。
[此贴子已经被作者于2010-12-7 23:31:50编辑过]
|
||||
-- 作者:kylin -- 发布时间:2010/12/7 13:23:00 -- 这个鱼和熊掌不可得兼的经验,收藏! |
||||
-- 作者:易服 -- 发布时间:2010/12/7 13:41:00 -- 有一按钮“编号”:自觉效率不高,能优化? Dim str As String |
||||
-- 作者:狐哥 -- 发布时间:2010/12/7 14:05:00 -- 添加到集合再对比,真是高。受用了。 |
||||
-- 作者:migold -- 发布时间:2010/12/7 14:25:00 -- 顶!试试去 |
||||
-- 作者:程兴刚 -- 发布时间:2010/12/7 14:33:00 -- 收藏慢慢消化! |
||||
-- 作者:狐狸爸爸 -- 发布时间:2010/12/7 14:35:00 -- 以下是引用易服在2010-12-7 13:41:00的发言:
有一按钮“编号”:自觉效率不高,能优化? Dim str As String
可以这么改改看看:
Dim str As String |
||||
-- 作者:易服 -- 发布时间:2010/12/7 14:43:00 -- 以下是引用狐狸爸爸在2010-12-7 14:35:00的发言:
可以这么改改看看:
Dim str As String 此主题相关图片如下:2010-12-7 14-42-11.png |
||||
-- 作者:狐狸爸爸 -- 发布时间:2010/12/7 15:02:00 -- 这都看不出来吗,我手误而已, 应该是:
For Each dr As DataRow In dic.keys
|
||||
-- 作者:狐狸爸爸 -- 发布时间:2010/12/7 15:04:00 -- 看来不单单查询这样,遍历过程中,任何涉及到所有行的操作,例如查找和计算都如此,我将第一列和第二列改为整数型,下面两段代码效率同样相差几百倍:
普通的: Dim v As Double
高效的,快了300倍: Dim Dic As new Dictionary(of DataRow, Integer) |