【问题标题】:Is there added overhead to looking up a column in a DataTable by name rather than by index?按名称而不是按索引查找 DataTable 中的列是否会增加开销?
【发布时间】:2010-04-13 18:04:09
【问题描述】:

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

【问题讨论】:

    标签: c# .net vb.net vb6


    【解决方案1】:

    是的,按名称而不是按索引查找列应该有一点开销。我不会担心,除非你一直在循环中查找同一列,就像在你的代码示例中一样。因为那样的话,轻微的开销可能会累积成可测量的开销,具体取决于表的行数。

    访问某一行的特定列值的最快方法使用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 Ben,您可以告诉您的团队负责人,这对于 VB6 也是很好的建议。例如这篇 Microsoft SQL Server Magazine 文章来自 2001 msdn.microsoft.com/en-us/library/aa496013(SQL.80).aspx
    • @MarkJ 那篇文章有很多很好的见解。在我自己在 .NET 中的测试中,按名称查找的成本相对较小,每 1,000,000 条记录的差异只有大约 300 毫秒。使用列名更具可读性和可维护性,以至于我不确定是否要通过 DataColumn 查找,除非我知道我将处理非常大的数据迭代。但我想这就是这个问题想要找出的:一种方法比另一种方法好多少?
    • @Ben,是的。我想我的意思是(恕我直言)即使在 VB6 中,您的团队领导也没有使用最好的技术。我认为 VB.Net 的情况没有改变。就个人而言,我也会在任何地方使用列名,除非测试证明在特定代码位中存在不可接受的性能。 (不管是VB6还是VB.Net)
    【解决方案2】:

    事实是

    1. 按索引获取列是对 ArrayList 的直接索引
    2. 如果名称查找区分大小写,则执行哈希表查找
    3. 如果名称查找不区分大小写,则会扫描列表中的名称并执行成本更高的区域设置敏感字符串比较。

    因此,按索引检索肯定是最高效的,但这有关系吗?

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

    1. 直接索引 - 13.3ms
    2. 不区分大小写的查找 - 109.11 毫秒
    3. 区分大小写的查找 - 109.24 毫秒

    因此,根据您的情况,您可以得出结论。

    【讨论】:

      【解决方案3】:

      是的,按名称而不是绝对索引查找列会产生开销(因为它只是定位列,然后以这种方式访问​​它)。

      话虽如此,这是相当不成熟的优化。 DataTable 将首先尝试以区分大小写的方式定位列,这种方式非常快。如果它无法以这种方式定位列,它会以 不区分大小写的方式查找,这只会稍微慢一些。

      访问数据绝对最快的方法是通过DataColumn 对象本身,因为这是基于索引和基于名称的访问器使用的。

      【讨论】:

        【解决方案4】:

        最好的方法是按列名查找索引并使用索引来定位列:

        Dim table As DataTable = ...
        Dim foo As int = table.Columns("Foo")
        
        For Each row As DataRow In table.Rows
            Dim data = row(foo)
        Next
        

        您正在按索引查找,您也可以从名称中猜测您正在阅读哪一列。另一个优点是,如果您更改“选择”查询中的字段顺序,您仍然会得到正确的值。另一方面,如果您对索引进行硬编码,您的代码就会中断。

        【讨论】:

          【解决方案5】:

          取决于您使用它的地方。在桌面应用程序启动时,这些小的低效率可能会累积到长时间的延迟。在鼠标和键盘事件上很可能不会。将时间花在函数分析上(将执行时间打印到 dbgview)很可能比优化这种低级的东西更有效率。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-07
            • 1970-01-01
            相关资源
            最近更新 更多