【问题标题】:Linq on generic List takes a lot of time通用列表上的 Linq 需要很多时间
【发布时间】:2015-02-09 19:21:27
【问题描述】:

我有一个数据库表,每秒从 6 个不同的测量站获取 7 个不同的值(即 42 个值)。数据不存储时间戳,只是一个“TickNumber”,然后根据 TickNumber 和开始测量的时间计算时间。

我无法控制。

但是,为了加快速度,我下载数据、分析数据并将其存储在另一个带有 asp.net 前端的数据库中。这个系统运行良好,每个人都很开心。

但是,分析部分需要很长时间,在使用性能分析器一段时间后,我发现了问题。

这会获取数据并返回一个列表。

Public Shared Function GetMeasuredValues(ByVal _startdate As Date, ByVal _enddate As Date) As List(Of MeasuredValues)
    Dim _db As New Quickview

    Dim functions() As Integer = System.Enum.GetValues(GetType(Enums.MeasuredValueTypes))
    Dim total_values As New List(Of MeasuredValues)

    'Finding max and min row values
    Dim stations() As Integer = {1, 2, 3, 4, 6, 16}
    For Each i In stations
        Dim station As Integer = i
        Dim local_start As Integer = DB.DateToPeriodNo(station, _startdate)
        Dim local_end As Integer = DB.DateToPeriodNo(station, _enddate)

        If local_start > 0 Then
            Dim all_values = (From vls In _db.MeasuredValues
                              Where vls.MeasValueId = station _
                              And functions.Contains(vls.FuncId) _
                              And vls.PeriodNo >= local_start And vls.PeriodNo <= local_end _
                              ).ToList
            Console.WriteLine("Data count for station " & i & ": " & all_values.Count)
            total_values.AddRange(all_values)
        End If
    Next

    Dim sorted_values = (From vls In total_values
                         Order By vls.Time Ascending, vls.MeasValueId Ascending).ToList

    Return sorted_values
End Function

这工作正常。数据量很大,传输数据占用了这一步消耗的大部分时间。

然后过滤此数据,为我提供一小时(07:00 到 07:59 等)的值。我使用这些值来计算该小时所需的平均值和总和。可悲的是,其中大部分是对数的,所以我不能使用。总和等

然后我做:

Dim all_values = DB.GetMeasuredValues(date_start, date_end)

....这只是给了我我需要的所有值的列表。

问题来了,这个查询似乎需要很长时间。

''' [in for-loop going through each hour between date_start and date_end, typically 24 hours]
Dim values_hour = (From vls In all_values
                   Where vls.MeasValueId = station _
                   And vls.FuncId = Func _
                   And vls.Time >= time_start And vls.Time < time_end).ToList

如果我相信性能分析器,这个简单的查询会占用 97% 的资源。我的计算似乎根本没有任何影响 (

我确定我做错了什么,但是什么?

【问题讨论】:

  • 也许您的数据库性能不佳?查看 LINQ 在数据库中生成和执行的查询。如果它进行全面扫描,它可能不适合您的用例。
  • 只是为了回应这个。它实际上是数据库。显然索引有问题。排序后,上面的代码实际上运行良好。

标签: vb.net performance linq list


【解决方案1】:

ToList 的调用会导致大量开销,因为它每次都需要为列表分配内存,然后填充该列表。
您是否尝试过删除它?
最重要的是,我会使用total_values.Concat(all_values) 而不是total_values.AddRange(all_values),然后就像你已经做的那样在最后调用ToList

而且我只会在调试模式或类似模式下写入数据计数,这样您就不会在性能很重要时在那里浪费时间。

【讨论】:

    【解决方案2】:

    由于您有按时间排序的数据,您可以使用SkipWhile/TakeWhile 从中获取时间块,然后应用其他过滤器。因此,您将批量数据枚举一次以获得所需的时间,并且仅将过滤器应用于该数据子集:

    Dim slice = all_values _
                .SkipWhile(Function(vls) vls.Time < time_start) _
                .TakeWhile(Function(vls) vls.Time < time_end)
    

    然后按Funcstation 过滤。

    【讨论】:

    • 这对你有意义吗?这取决于数据的内容。如果您希望通过首先在 Func 或 station 上过滤来获得最小的块,您可能需要更改数据的初始排序顺序并在最具选择性的属性上执行 SkipWhile/TakeWhile
    猜你喜欢
    • 2015-06-01
    • 2020-03-19
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    相关资源
    最近更新 更多