【问题标题】:Is this query being executed on an in-memory collection, or in the database?此查询是在内存中的集合上执行的,还是在数据库中执行的?
【发布时间】:2011-02-15 17:59:01
【问题描述】:

我在一个论坛网站上使用实体框架,并且有两个带有问题的查询示例。

查询 #1) 该查询应该获取论坛中所有主题的主题计数。它是否在 SQL 中执行计数,以便我只得到一个数字?还是将所有主题拉入内存,然后统计集合中的主题?

            return DBContext.Topics
                .Where(x => !x.ModsOnly)
                .Where(x => !x.Board.ModsOnly)
                .Where(x => !x.Board.Hidden)
                .Count();

查询#2)这个查询应该获取所有主题,按最后回复日期(如果没有回复,则按主题日期)对它们进行排序。然后它计算结果,并对结果进行分页。这个查询中有多少是在数据库中执行的?这个查询需要 FOREVER,所以我认为它会在某个时间点将所有主题拉入内存,可能在分页生效之前。

            var query = DBContext.Topics
                    .Where(x => !x.ModsOnly)
                    .Where(x => !x.Board.ModsOnly)
                    .Where(x => !x.Board.Hidden)
                    .OrderByDescending(x => x.GlobalSticky)
                    .ThenByDescending(x => x.Replies
                        .Where(r => !r.ModsOnly)
                        .Any() ? x.Replies
                            .Where(r => !r.ModsOnly)
                            .Max(r => r.PostedDate) : x.PostedDate);
                int totalTopics = query.Count();
                if (totalTopics > itemsPerPage)
                    return query.Skip((page - 1) * itemsPerPage).Take(itemsPerPage);
                else
                    return query;

我不是 LINQ 专家,因此不胜感激。我知道这是一个复杂的查询,但如果有人可以花一点时间来解析它并找出我在哪里/如果我在某个地方出错了,那将非常有帮助。

注意:我试图避免在名为“LastReplyDate”的主题中创建一个列并以此为主题排序。出于我的目的,我真的希望通过最后一个回复来完成排序,而不是通过关于主题的任意列,我可能必须在每个添加/删除的回复中进行更新。 但是,如果你们认为没有其他方法可以实现我的目标,我会考虑这条路线。

【问题讨论】:

  • @Chevex 是不是更容易附加 sqlprofiler 来检查查询的性能和行为?
  • @marc 嗯,我不知道我能做到这一点。这是 EF 上下文对象上的方法吗? @rene,我想,介意发布一个答案并举例说明如何做到这一点?
  • 公平地说,在 linq-to-SQL(只是 ctx.Log = Console.Out)中更容易 - 使用 EF 的 SQL 分析器工具,或者可能是 Ayende 的分析器
  • @Chevex 如果您使用的是 SQL Server,SSMS 有一个 SQL Server Profiler 工具,您可以设置它来跟踪数据库上的 RPC。
  • 还有一个选择是使用 LINQPad,它可以理解您的 EF 模型并为您提供 SQL 跟踪。

标签: c# linq entity-framework entity-framework-4 linq-to-entities


【解决方案1】:

您的第一个示例将使用一个数据库查询。是的,它在 SQL 中计算。

您的第二个将使用两个。一个用于int totalTopics = query.Count();,一个用于分页结果。

它们中的任何一个都不会在内存中进行限制等。

【讨论】:

  • 嗯,由于它通过查询回复日期来排序主题的方式,查询会花费这么长时间吗?
  • 感谢您回答我最初的问题。这对我的问题没有帮助,但确实回答了这个问题。非常感谢! +1
  • 查询可能需要很长时间,原因有很多。也许数据库查询很慢。也许 EF 开销很高。也许它们是不必要的复杂。正如其他人所提到的,您需要对此进行分析。
  • 是的,我无法对其进行分析。我对数据库没有正确的权限。但是,我确实按照您的建议使用了 LINQpad,不仅查询在数据库中正确执行,而且它们都非常快。我确定我还有其他问题正在发生。感谢您的帮助!
【解决方案2】:

查询将在数据库上执行,但对于第二个查询,我建议取出 order by 子句,因为它们对于计数操作不是必需的,并且会减慢速度。

【讨论】:

  • 好的,很简单,但是即使在执行第二个查询之前,它已经获得了第一个计数查询的计数,查询仍然很慢。
  • @Chevex 你是说你的 Query #1) 很慢吗?
  • 不,查询 1 快如闪电。查询 2 很慢。我只是说查询 2 仍然很慢,即使删除了 order by 子句。
猜你喜欢
  • 1970-01-01
  • 2013-09-24
  • 2018-02-09
  • 2021-10-15
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多