我有一个数据库表,每秒从6个不同的测量站(即42个值)获得7个不同的值。数据不存储时间戳,只存储“TickNumber”,然后根据TickNumber和测量开始时间计算时间。
我无法控制这一点。
然而,为了加快速度,我下载数据,分析数据并将其存储在另一个带有asp.net前端的数据库中。这个系统运作良好,每个人都很开心。
然而,分析部分正在进行中,在使用性能分析器一段时间后,我发现了问题。
这将获取数据并返回List。
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%的资源。我的计算似乎没有任何影响(<0.2%)。
我确定我做错了什么,但是什么?
答案 0 :(得分:2)
对ToList
的调用会导致很多开销,因为它需要每次为列表分配内存,然后填写该列表。
你试过删除吗?
最重要的是,我会使用total_values.Concat(all_values)
代替total_values.AddRange(all_values)
,然后就像你已经做的那样在最后调用ToList
。
如果处于调试模式或类似的情况下,我只会写入数据计数,这样,当性能很重要时,你就不会在那里浪费时间。
答案 1 :(得分:2)
由于您按时间排序数据,因此您可以使用SkipWhile/TakeWhile
从中获取时间块,然后应用其他过滤器。因此,您只需枚举批量数据一次即可获得所需的时间,并仅将过滤器应用于此数据子集:
Dim slice = all_values _
.SkipWhile(Function(vls) vls.Time < time_start) _
.TakeWhile(Function(vls) vls.Time < time_end)
然后按Func
和station
进行过滤。