【问题标题】:DataView.RowFilter Vs DataTable.Select() vs DataTable.Rows.Find()DataView.RowFilter 与 DataTable.Select() 与 DataTable.Rows.Find()
【发布时间】:2010-05-14 06:43:46
【问题描述】:

考虑下面的代码:

Dataview someView = new DataView(sometable)
someView.RowFilter = someFilter;

if(someView.count > 0) {  …. }

相当多的文章说 Datatable.Select() 比使用 DataViews 更好,但这些都是在 VS2008 之前。

Solved: The Mystery of DataView's Poor Performance with Large Recordsets
Array of DataRecord vs. DataView: A Dramatic Difference in Performance

在这个主题上谷歌搜索,我发现一些文章/论坛主题提到 Datatable.Select() 本身有很多错误(对此不确定)并且在各种情况下表现不佳。

关于 msdn 上的这个 (Best Practices ADO.NET) 主题,建议如果在数据表上定义了主键,则应使用 findrows() 或 find() 方法代替 Datatable.Select()。

这篇文章here (.NET 1.1) 对所有三种方法以及更多方法进行了基准测试。但这是针对 1.1 版的,所以不确定这些现在是否仍然有效。根据这个 DataRowCollection.Find() 优于所有方法,Datatable.Select() 优于 DataView.RowFilter。

所以我很困惑在数据表中查找行的最佳方法可能是什么。或者没有单一的好方法可以做到这一点,根据场景存在多种解决方案?

【问题讨论】:

    标签: .net visual-studio-2008 performance ado.net datatable


    【解决方案1】:

    您正在寻找“在数据表中查找行的最佳方法”,所以我首先要问:“最佳”是为了什么?我认为,任何技术都有可能比其他技术更适合的场景。

    首先,让我们看一下DataView.RowFilter:DataView 在数据绑定方面有一些优势。它非常面向视图,因此它具有强大的排序、过滤或搜索功能,但会产生一些开销并且未针对性能进行优化。我会选择 DataView.RowFilter 用于较小的记录集和/或您可以利用其他功能(例如,直接将数据绑定到视图)。

    您可以在较早的帖子中阅读有关 DataView 的大多数事实仍然适用。

    其次,如果你只想要一次点击,你应该更喜欢DataTable.Rows.Find 而不是DataTable.Select。为什么? DataTable.Rows.Find 只返回一行。本质上,当您指定主键时,会创建一个二叉树。这有一些相关的开销,但极大地加快了检索速度。

    DataTable.Select 速度较慢,但​​如果您有多个条件并且不关心索引或未索引的行,它会非常方便:它基本上可以找到所有内容,但没有针对性能进行优化。本质上,DataTable.Select 必须遍历整个表并将每条记录与您传入的条件进行比较。

    我希望这个小概述对您有所帮助。

    我建议看看 this article,它对我的​​性能问题很有帮助。这篇文章包含了一些引用。

    一点更新: 顺便说一句,这似乎有点超出您的问题范围,但它几乎总是在后端进行过滤和搜索的最快解决方案。如果您想要简单性并有一个 SQL Server 作为后端并在客户端使用 .NET3+,请选择 LINQ-to-SQL。搜索 Linq 对象非常舒适,并且会创建在服务器端执行的查询。虽然 LINQ-to-Objects 也是一种非常舒适但速度较慢的技术。如果你还不知道......

    【讨论】:

    • 我刚刚发现 .Select 和 RowFilter 技术的结果不同的情况。在我的例子中,Select 返回了 532 行,RowFilter 返回了 540。我发现差异与表数据中的额外空格有关,并通过在 select 语句 TRIM(VendorNumber) = '500' 中使用 Trim 来解决它
    【解决方案2】:

    Thomashaid 的帖子总结得很好:

    • DataView.RowFilter 用于绑定。
    • DataTable.Rows.Find 仅用于按主键搜索
    • DataTable.Select 用于多列搜索,也用于指定顺序。

    避免在循环中创建许多 DataView 并使用它们的 RowFilters 来搜索记录。这将大大降低性能。

    我想补充一点,DataTable.Select 可以利用索引。您可以通过创建 DataView 并指定排序顺序来在 DataTable 上创建索引:

    DataView dv = new DataView(dt);
    dv.Sort = "Col1, Col2";
    

    然后,当您调用DataTable.Select() 时,它可以在运行查询时使用该索引。我们已经使用这种技术在多次使用相同查询的地方显着提高了性能。 (请注意,这是在 Linq 存在之前。)

    诀窍是为Select 语句正确定义排序顺序。因此,如果您的查询是“Col1 = 1 和 Col2 = 4”,那么您将需要“Col1, Col2”,如上例所示。

    请注意,索引的创建可能取决于创建 DataView 的实际调用。我们必须使用 new DataView(DataTable dt) 构造函数,然后在单独的步骤中指定 Sort 属性。不同的 .NET 版本的行为可能会略有不同。

    【讨论】:

    • 哇,这超级方便。我不敢相信这在 MSDN 上没有记录。使用类似 1 行代码,我大大提高了 DataTable.Select() 调用的性能,而无需执行所有愚蠢的 FindRows() 和 Dictionary 工作。谢谢
    • 超级棒,这让我很开心。现在查询速度提高了 300%!
    • 如果您逐步浏览底层的 .Net 源代码,您会发现如果条件合适,通常 .Select() 确实会自己创建索引。例如当使用像“col1 = 3 and col2 = 4”这样的简单表达式时。您可以通过在选择后检查表的私有 [indexes] 字段来看到这一点。在这些情况下,无需创建 DataView。上面的答案对我也不起作用,我需要用表构造函数创建一个 DataView,然后单独设置 [Sort] 属性。不知道为什么...
    • 我们的代码具有相同的模式:1)使用DataTable-only 构造函数创建DataView 2)设置排序属性。我会在答案中注明。
    • @paul 假设在同一个文件中有一个查找函数,该函数将数据表作为参数。那么我如何在该函数中使用这个概念。它会自动使用我在上面创建的视图,还是必须将其传递给函数而不是数据表。
    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 2018-11-16
    • 2011-12-06
    • 2016-03-11
    • 1970-01-01
    • 2011-03-09
    相关资源
    最近更新 更多