实体框架4.1查询需要很长的时间(5秒)才能完成
我有DbContext(称为“MyContext”),其中包含大约100个DbSets。实体框架4.1查询需要很长的时间(5秒)才能完成
在域类中,我有一个包含10个直接子类的Document类(如PurchaseOrder,RequestForQuotation等)。 heirarchy被映射为TPT策略。 也就是说,在我的数据库中,有一个Document表和其他表,如子类的PurchaseOrder和RequestForQuotation。
当我做一个查询,如:
Document document = myContext.Documents.First();
查询花了5秒,无论是我第一次运行它或随后。
的查询,如:
Document document = myContext.Documents.Where(o => o.ID == 2);
还需要长达。
这是EF4.1的问题(如果是这样,EF4.2的帮助)还是这是查询代码的问题?
我不能肯定,通过代码优先实际使用的ObjectQuery但是你可以尝试调用.ToTraceString()方法对他们看到的是生成了什么SQL,像这样露出DbSet:
var query = myContext.Documents.Where(o => o.ID == 2);
Debug.WriteLine(query.ToTraceString());
一旦你得到SQL,你可以确定它是查询还是EF引起延迟。根据基类的复杂性,查询可能会包含许多额外的列,这可以通过投影来避免。使用预测,可以这样进行查询:
var query = from d in myContext.Documents
where d.ID == 2
select new
{
o.Id
};
这应该基本上执行SELECT ID FROM Documents WHERE ID = 2
查询,你可以测量这个需要多久才能获得进一步的信息。当然,预计的查询可能不适合您的需求,但它可能会让您走上正轨。如果这仍然需要5秒钟,您应该查看数据库本身而不是EF的性能问题。
更新 显然与代码首先,你可以使用的ToString(),而.ToTraceString(),感谢Slauma用于察觉。
您是否尝试使用SQL配置文件查看实际发送到数据库的内容?这可能是因为您的文档中有太多连接未设置为延迟加载,因此查询必须一次完成所有连接,这会导致列数过多。尝试发送一个简单的查询只有一个返回列。
正如您可以阅读here,在EF中有关于TPT的一些性能问题。
的EF团队公开宣布了一些修复的June 2011 CTP,包括TPT查询优化,但不包括在EF 4.2,你可以在评论中读取this answer。
在最糟糕的情况下,这些修补程序将仅在.NET 4.5中发布。我希望它会更快......
我认为TPT继承很可能是问题的根源。 10个表的SQL查询将会很糟糕。 –
TPT继承可能非常有用,但我也有关于其性能的问题。我正在使用5-6张桌子。有10张桌子,我想它会变得更糟。这是我等待这些优化被纳入EF的原因之一。 –
假设TPT是原因,您使用其他解决方案来解决它吗? – swirlobt
我刚刚在ExecuteFunction中存在5秒的延迟,这个存储过程在从SQL Management Studio调用时即时运行。我通过重写程序来修复它。
看来EF(和SSRS BTW)会尝试在存储过程和某些(通常是复杂的)过程中执行类似“准备”的操作,这可能需要很长时间。
一个快速和肮脏的解决办法是复制,然后用内部变量替换您的SP参数:
create proc ListOrders(@CountryID int = 3, @MaxOrderCount int = 20)
as
declare @CountryID1 int, @MaxOrderCount1 int
set @CountryID1 = @CountryID
set @MaxOrderCount1 = @MaxOrderCount
select top (@MaxOrderCount1) *
from Orders
where CountryID = @CountryID1
'query.ToString()',而不是'ToTraceString()'显示了SQL使用'DbContext'时。 – Slauma
@Slauma谢谢,这会派上用场。 –