是否增加了按名称而不是按索引查找DataTable中的列的开销?

时间:2010-04-13 18:04:09

标签: c# .net vb.net vb6

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的性能优势的情况?

5 个答案:

答案 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. 通过索引获取列是ArrayList
  2. 的直接索引
  3. 如果名称查找区分大小写,则执行哈希表查找
  4. 如果名称查找不区分大小写,则会扫描列表以查找名称,并执行更昂贵的区域设置敏感字符串比较。
  5. 因此,索引检索肯定是性能最高的,但这有关系吗?

    在我的机器上进行一些基本的(读取天真的)测试我发现使用上述索引机制对列进行1,000,000次访问需要以下时间

    1. 直接指数 - 13.3毫秒
    2. 不区分大小写的查找 - 109.11ms
    3. 区分大小写的查找 - 109.24ms
    4. 因此,根据您的情况,您可以得出结论。

答案 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)上比将优化这种低级别的东西更有效率。