在DataTable
对象中,是否增加了按名称thisRow("ColumnA")
而不是列索引thisRow(0)
查找列值的开销?这可能是一个问题。
我在一个有很多编写VB6代码经验的团队工作,我注意到没有为DataTable
对象或数据网格按名称进行列查找。即使在.NET代码中,我们也使用一组整数常量来引用这些类型的对象中的列名。我问我们的团队负责人为什么会这样,他提到在VB6中,按列名而不是索引查找数据会产生大量开销。 .NET仍然如此吗?
示例代码(在VB.NET中,但同样适用于C#):
Public Sub TestADOData()
Dim dt As New DataTable
'Set up the columns in the DataTable '
dt.Columns.Add(New DataColumn("ID", GetType(Integer)))
dt.Columns.Add(New DataColumn("Name", GetType(String)))
dt.Columns.Add(New DataColumn("Description", GetType(String)))
'Add some data to the data table '
dt.Rows.Add(1, "Fred", "Pitcher")
dt.Rows.Add(3, "Hank", "Center Field")
'Method 1: By Column Name '
For Each r As DataRow In dt.Rows
Console.WriteLine( _
"{0,-2} {1,-10} {2,-30}", r("ID"), r("Name"), r("Description"))
Next
Console.WriteLine()
'Method 2: By Column Name '
For Each r As DataRow In dt.Rows
Console.WriteLine("{0,-2} {1,-10} {2,-30}", r(0), r(1), r(2))
Next
End Sub
是否存在方法2提供优于方法1的性能优势的情况?
答案 0 :(得分:7)
是,按名称而不是索引查找列应该会有轻微的开销。我不担心它,除非你继续在循环中查找同一列,就像在代码示例中一样。因为这会导致轻微的开销累积到可测量的开销,具体取决于表的行数。
访问特定列的某些行的值的最快方式是使用DataColumn
对象本身进行查找。例如:
Dim dt As DataTable = ...
Dim idColumn As DataColumn = dt.Columns("ID")
Dim nameColumn As DataColumn = dt.Columns("Name")
Dim descriptionColumn As DataColumn = dt.Columns("Description")
For Each r As DataRow In dt.Rows
' NB: lookup through a DataColumn object, not through a name, nor an index: '
Dim id = r(idColumn)
Dim name = r(nameColumn)
Dim description = r(descriptionColumn)
...
Next
最后一条建议:我强烈建议您不要使用数字索引!它使您的代码更加脆弱,并且更难以理解和维护:一旦列的逻辑顺序发生变化,您需要相应地调整您的代码,可能在几个地方(并且您可能很容易监督其中一个,领先到错误)。如果您使用列名或DataColumn
对象本身进行查找,则可以更改列的顺序,而无需更改其余代码。
答案 1 :(得分:2)
事实是
因此,索引检索肯定是性能最高的,但这有关系吗?
在我的机器上进行一些基本的(读取天真的)测试我发现使用上述索引机制对列进行1,000,000次访问需要以下时间
因此,根据您的情况,您可以得出结论。
答案 2 :(得分:1)
是的,通过名称而不是绝对索引查找列会产生开销(因为它只是找到列,然后以这种方式访问它)。
话虽如此,那是相当不成熟的优化。 DataTable
将首先尝试以区分大小写的方式查找列,这非常快。如果它无法以这种方式找到列,它会以不区分大小写的方式查找,这种方式只会稍慢。
访问数据的绝对最快方式是通过DataColumn
对象本身,因为这是基于索引和基于名称的访问者使用的方式。
答案 3 :(得分:1)
最好的方法是按列名查找索引并使用索引来定位列:
Dim table As DataTable = ...
Dim foo As int = table.Columns("Foo")
For Each row As DataRow In table.Rows
Dim data = row(foo)
Next
您正在按索引查找,您还可以从名称中猜出您正在阅读的列。另一个优点是,如果您更改选择查询中的字段顺序,您仍将获得正确的值。另一方面,如果您使用硬编码索引,您的代码就会中断。
答案 4 :(得分:0)
取决于您使用它的地方。在桌面应用程序启动时,这些小的低效率可能会累积到长时间的延迟。在鼠标和键盘事件上很可能不是。将时间花在功能分析(将执行时间打印到dbgview)上比将优化这种低级别的东西更有效率。