【问题标题】:How to Optimize below linq query如何优化下面的 linq 查询
【发布时间】:2015-12-03 09:42:12
【问题描述】:

我在 vb.net 中有以下 Linq 查询,3000 条记录需要 2-3 分钟。我想优化它。请给我建议

Dim sessionsEligibleForDeletion As List(Of Integer) = Nothing

以下查询需要很长时间。

sessionsEligibleForDeletion = 
    (From row In dt.AsEnumerable()
        Group row By sessionID = row.Field(Of Int32)("sessionID") Into SessionGroup = Group
        Select New With 
        {
            sessionID,
            .eligibleForDeletion = SessionGroup.Count(Function(r) r.Field(Of Int32)("sessionID")) > totalCriterias - 1
        }).
            Where(Function(rr) rr.eligibleForDeletion = True).
            Select(Function(rr) rr.sessionID).ToList()

【问题讨论】:

  • 数据库查询计划是什么样的? (即,使用合理的索引,查询可能是合理的。)
  • 什么是distinctReportNo?此外,这是 Linq-To-DataTable,它是 Linq-To-Objects 的子集。如果您可以在数据库中进行过滤,那可能是最有效的方法。
  • 我已经更新了问题请看一下。它与数据库无关。它仅与数据行和数据表有关
  • 你想达到什么目的?首先从表中选择所有reportNo,然后选择此列表中具有reportNo 的所有行。这是所有行,因为您使用的是相同的源。所以前两个查询已经没有意义了。
  • 是的,你是对的..但是 sessionEligibleForDeletion 获取字段的最后一个查询需要时间...想要优化它。

标签: vb.net performance linq optimization


【解决方案1】:

所以dtDataTable,首先使用AsEnumerable 而不是DataTable.Select,它会返回一个新的DataRow(),其中包含所有行以节省内存。

更重要的是,您从表中选择所有reportNo,然后选择此列表中具有reportNo 的所有行。这是所有行,因为您使用的是相同的源。所以前两个查询已经毫无意义。

此外,您将按SessionID 将所有行分组到一个名为SessionGroup 的组中,这些组包含DataRows 并且每一行都具有相同的SessionID,因为您已按该列进行了分组。这就是为什么我不理解SessionGroup.Count(...sessionID)。无论如何,将Option Strict 设置为On 将无法编译,因为Enumerable.Count 采用布尔谓词而不是整数。也许你只是想使用SessionGroup.Count() > totalCriterias - 1,所以没有谓词。

现在谈谈您的实际性能问题。您想查找所有出现次数超过totalCriterias - 1SessionID?那么这个使用HashSet(Of Int32)Dictionary(Of int32, Int32)的简单循环会更有效,只需要一个枚举:

Dim sessionsEligibleForDeletion As New HashSet(Of Integer)
Dim sessionIdCount As New Dictionary(Of Int32, Int32)
For Each row As DataRow In dt.Rows
    Dim sessionID = row.Field(Of Int32)("sessionID")
    Dim count As Int32
    sessionIdCount.TryGetValue(sessionID, count)
    count += 1
    sessionIdCount(sessionID) = count
    If count > totalCriterias - 1 Then sessionsEligibleForDeletion.Add(sessionID)
Next

如果您需要哈希集中的List(Of Int32),请使用sessionsEligibleForDeletion.ToList()

如果你坚持使用 LINQ 查询,你可以使用这个:

Dim sessionsEligibleForDeletion As List(Of Int32) = dt.AsEnumerable().
    GroupBy(Function(row) row.Field(Of Int32)("sessionID")).
    Where(Function(grp) grp.Count() > totalCriterias - 1).
    Select(Function(grp) grp.Key).
    ToList()

【讨论】:

  • 感谢您的建议。通过直接删除两个不必要的语句并在Linq中直接使用dt,它已经优化了很多。 sessionEligibleForDeletion = (From row In dt.AsEnumerable() Group row By sessionID = row.Field(Of Int32)("sessionID") Into SessionGroup = Group Select New With {
猜你喜欢
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
相关资源
最近更新 更多