【问题标题】:Getting Count from Large IEnumerable从大型 IEnumerable 中获取计数
【发布时间】:2018-07-09 21:10:39
【问题描述】:

我有一个包含 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 的计数有一些规则,并且要获得计数必须对其进行计数。

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

【问题讨论】:

  • FilterResultsSet() 看起来像什么?它是否返回IQueryable&lt;&gt;?如果是这样,并且如果看起来很快,可能是这样,直到你真正做到了.Select(),你并没有具体化记录,而且你在FilterResultsSet() 中所做的任何事情都可能效率低下
  • NULLable和针对此类的测试优化不佳。

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


【解决方案1】:

在听取了两个 cmets 的建议后,我尝试从搜索中删除 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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2010-09-06
    相关资源
    最近更新 更多