从大型IEnumerable获取计数

时间:2018-07-09 21:10:40

标签: mysql performance linq .net-core entity-framework-6

我有一个3个内部联接表的数据集,该表由一个MySQL数据库中的大约18,000条记录组成。我的函数应该获取所有相关数据,然后通过用户提供的某些参数对其进行过滤,然后返回要应用该过滤器的项目数。

当我使用标准数据读取器时,此方法工作正常,但是我只是将应用程序移至使用实体框架来尝试并提高性能,为此,我正在使用LazyLoadingProxies-我认为这与问题有关。

我功能的主要部分是

  1. 获取所有数据项
  2. (对于每个参数)克隆所有数据项
  3. 获取已过滤项目的数量

代码看起来像这样

var EventsLogged = context.EventLogs.Where(x => x.Event.GameId == request.GameId
                                     && (!request.EventId.HasValue || x.EventId == request.EventId.Value)
                                     && (!request.StartTime.HasValue || x.Created >= request.StartTime.Value)
                                     && (!request.EndTime.HasValue || x.Created <= request.EndTime.Value));




if (EventsLogged.Count() <= 0)
{
    response.AddErorrMessage("No data found for Event.");
}
else
{
    //Some other stuff happens here not related to do with working on the parameters

    IEnumerable<EventLogs> filteredEvents = EventsLogged;
    filteredEvents = FilterResultsSet(filteredEvents, parametervalue);

    return filteredEvents.Select(x => x.UserId).Distinct().Count();
}

该函数正常工作,过滤很好,然后当我们按下Select.Distinct()。Count()时,处理时间激增到了惊人的水平-我等了大约20分钟才放弃。

在输出窗口中,我可以看到正在输出SQL的各个部分,就像此时实际上正在执行查询一样,但是一次仅记录1条。

从我已经看过的内容来看,围绕获取IEnumerable的计数有一些规则,要获得IEnumerable的计数,必须对其进行计数。

由于我不在乎此查询中的任何内容,仅是计数,有什么方法可以实现这一目标-还是我需要重新考虑整个策略。

1 个答案:

答案 0 :(得分:0)

在遵循两个注释的建议后,我尝试从搜索中删除NULLABLE项目。但是,这并没有进行更多优化。

怀疑是LazyLoadingProxies引起了问题-运行.SELECT()实体框架时,正在尝试填充我的数据集,但是它没有我真正想要的上下文,因此它试图解决该问题,并且获取大量数据;其中也有一个关系循环,即4个表通过外键链接在一起-因此我想它正在尝试同时解决所有问题。

当我删除延迟加载时,我不得不使用.Include()和.ThenInclude()选项指定要解析的导航属性。

工作代码如下

List<EventsLogged> EventsLogged = context.EventLogs
                                            .Include(log => log.Session)
                                            .Include(log => log.EventParameterValues)
                                                .ThenInclude(val => val.EventParameter)
                                            .Where(x => x.Event.GameId == request.GameId).ToList();