为什么在循环访问DataTable列时第二种方法会变慢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在循环访问DataTable列时第二种方法会变慢相关的知识,希望对你有一定的参考价值。

我有一个非常大的DataTable~4百万行。

我需要计算表中的列,如果我在方法(Go1)中处理整个列,它比Go2更快,我遍历行并调用每行的方法。

我需要使用Go2方法,因为稍后我需要向表中添加更多行并更新所有列。

但是为什么Go2接近慢 - 它只是每次调用ProcessRow()的开销吗?

有解决方法吗?

public static void AddSignal()
{
    foreach (DataRow row in Data.Rows)
    {
        row[x] = (invertSignal ? -1:1)*Math.Sign(row.Field<double>(y) - row.Field<double>(y));
    }
}

public class ByRowAddSignal
{
    DataRow row;

    public ByRowAddSignal()
    {

    }

    public void ProcessRow(int r)
    {
        row = Data.Rows[r];
        row[x] = (invertSignal ? -1 : 1) * Math.Sign(row.Field<double>(y) - row.Field<double>(y));
    }
}

Public static DataTable Data;
public void Go1()
{
      Data = LoadData();

      AddSignal();
}

public void Go2()
{
      Data = LoadData();

      ByRowAddSignal byRowAddSignal = new ByRowAddSignal ();

      for (int r = 0; r < Data.Rows.Count; r++)
      {
            byRowAddSignal.ProcessRow(r);
      }
}
答案

查看DataRowCollection的代码,我们发现以下内容:

public DataRow this[int index]
{
    get
    {
        return ((RBTree<DataRow>)this.list)[index];
    }
}

RBTree<K>实际上是一个树而不是数组支持列表,因此索引到它是很复杂的,因为在每个索引调用中你需要迭代到aproproate元素。来自RBTree<K>的代码显示了这一点:

public K this[int index]
{
    get
    {
        return this.Key(this.GetNodeByIndex(index).NodeID);
    }
}
private NodePath GetNodeByIndex(int userIndex)
{
    int num;
    int mainTreeNodeID = default(int);
    if (this._inUseSatelliteTreeCount == 0)
    {
        num = this.ComputeNodeByIndex(this.root, userIndex + 1);
        mainTreeNodeID = 0;
    }
    else
    {
        num = this.ComputeNodeByIndex(userIndex, out mainTreeNodeID);
    }
    if (num == 0)
    {
        if (TreeAccessMethod.INDEX_ONLY == this._accessMethod)
        {
            throw ExceptionBuilder.RowOutOfRange(userIndex);
        }
        throw ExceptionBuilder.InternalRBTreeError(RBTreeError.IndexOutOFRangeinGetNodeByIndex);
    }
    return new NodePath(num, mainTreeNodeID);
}
private int ComputeNodeByIndex(int x_id, int index)
{
    while (x_id != 0)
    {
        int num = this.Left(x_id);
        int num2 = this.SubTreeSize(num) + 1;
        if (index < num2)
        {
            x_id = num;
        }
        else
        {
            if (num2 >= index)
            {
                break;
            }
            x_id = this.Right(x_id);
            index -= num2;
        }
    }
    return x_id;
}

注意使用ILSpy反编译的代码

以上是关于为什么在循环访问DataTable列时第二种方法会变慢的主要内容,如果未能解决你的问题,请参考以下文章

c#中datatable绑定comboBox显示数据有重复怎么处理?取值时未用SQL语句。

为啥在尝试访问 HTML 表中的前两列时会出现错误?

javascript,为啥在播放视频时第二行无法从第一行替换?

在查询结构列时面临访问被拒绝

当您需要基于另一列更新列时,在 Pandas 中循环的替代方法

C#中关于SqlDataAdapter的Update(dataTable)方法