【发布时间】:2014-08-22 15:31:33
【问题描述】:
我在使用以下实体框架查询时遇到性能问题:
using (MyEntities context = new MyEntities())
{
return context.Companies
.Single(c => c.CompanyId == company.CompanyId)
.DataFile.Sum(d => d.FileSize);
}
在 SQL 探查器中进行跟踪时,我看到以下 SQL 命令:
exec sp_executesql N'SELECT
[Extent1].[DataFileID] AS [DataFileID],
[Extent1].[LocalFileName] AS [LocalFileName],
[Extent1].[ServerFileName] AS [ServerFileName],
[Extent1].[DateUploaded] AS [DateUploaded],
[Extent1].[FileSize] AS [FileSize],
[Extent1].[CompanyID] AS [CompanyID]
FROM [dbo].[DataFile] AS [Extent1]
WHERE [Extent1].[CompanyID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=16
据我所知,所有数据文件行都被返回(超过 10,000 行)到内存中,然后 Sum() 正在发生。
编辑:
根据 Patryk 的建议,我已将查询更改为:
using (MyEntities context = new MyEntities())
{
return context.Companies
.Where(c => c.CompanyId == company.CompanyId)
.Select(x => x.DataFiles.Sum(d => d.FileSize))
.Single();
}
SQL 跟踪如下所示:
SELECT TOP (2)
(
SELECT
SUM([Extent2].[FileSize]) AS [A1]
FROM
[dbo].[DataFile] AS [Extent2]
WHERE
[Extent1].[CompanyId] = [Extent2].[CompanyID]
) AS [C1]
FROM
[dbo].[Company] AS [Extent1]
WHERE
[Extent1].[CompanyId] = 16
这好多了,但是,基本上我只想要这样简单快捷的东西:
SELECT SUM(FileSize) FROM DataFile WHERE CompanyId = 16
【问题讨论】:
-
也许稍微改变一下查询,让它看起来更像 SQL-ish 就可以了:
context.Companies.Where(c => ...).Select(x => x.DataFile.Sum(d => d.FileSize)).Single()。这样,表达式访问者可能会更容易一点,生成的 SQL 可能会更好;如果没有帮助,您可以在Select之后手动调用AsEnumerable,看看是否有任何改变。 -
谢谢。查看我的编辑:)
-
@PatrykĆwiek 正确优化,但推理很糟糕。问题归结为延迟加载。
-
如果你想要那个确切的查询而不是只使用
context.Companies.SqlQuery("...")- 我怀疑这两个查询之间的性能差异很大。 -
@Aron 在这种特殊情况下 - 是的,在调用
Single之后,我们会收到一个延迟加载的集合。当您将 LINQ 查询重新构造为更像 SQL 时,通常可以避免很多问题 - 我们不能忘记它在某一时刻被转换为 SQL。
标签: c# .net linq entity-framework entity-framework-5