我有一个由几个实体组成的数据模型,所有实体都是相互关联的,总共大约有80个表。
我开始以生产形式获取代码,并且在这个过程中我将从延迟加载所有内容(它使我的开发生活更容易)转换为在我不需要所有相关数据的情况下进行急切加载,或者它只是表示要发送给客户端的数据太多,这只是浪费带宽。
然而,我只是注意到,对于至少一些实体来说,急切加载我需要的东西比延迟加载所有数据要慢得多。
这是一个例子,我可以懒惰加载“请求”对象:
db.ContextOptions.LazyLoadingEnabled = true;
request = db.requests.Where(rq => rq.idrequest == rID).FirstOrDefault();
或急切地说:
db.ContextOptions.LazyLoadingEnabled = false;
request = db.request_objects.Include("service_objects.task_objects.task_parameters.parameter_values.address1").Include("service_objects.task_objects.task_parameters.parameter_values.attachment").
Include("service_objects.task_objects.task_parameters.parameter_values.phone_nbrs").Include("service_objects.task_objects.task_parameters.parameter_values.stored_texts").
Include("service_objects.task_objects.parent_tasks").Include("service_objects.task_objects.contact_objects").
Include("service_objects.service_parameters.parameter_values.address1").Include("service_objects.service_parameters.parameter_values.attachment").
Include("service_objects.service_parameters.parameter_values.phone_nbrs").Include("service_objects.service_parameters.parameter_values.stored_texts").
Include("service_objects.stored_texts").
Include("request_attachments.attachment").Include("request_notes.note").
Include("request_contacts.contact_objects").Include("contact_objects").
Include("contact_objects1").Include("contact_objects2").
Include("request_objects_links.request_objects1").Include("stored_texts").
Include("company_objects").
Where(ro => ro.idrequest_objects == rID).FirstOrDefault();
在大多数情况下,急切加载请求比懒惰加载要快几百倍或几千倍(!!!),尽管延迟加载通常会加载大量额外数据。 我的意思是,使用急切加载需要2到3秒,而在大多数情况下(通常小于10毫秒)延迟加载需要不到40毫秒(我使用System.diagnostics.Stopwatch获得了这些时间)。
我不是SQL专家,对SQL优化一无所知,但我无法完全理解为什么加载更少的数据更加昂贵。
我的任何见解或明显的错误? 谢谢!
修改
从Brokenglass的回答来看,我不够清楚:o)。这段代码只是WCF服务函数的一部分,非常简单:
[OperationContract]
public request LoadRequestByID(int rID)
{
request res = null;
try
{
DBEntities db = new DBEntities();
res = db.request_objects.Where(ro => ro.idrequest_objects == rID).FirstOrDefault();
}
catch (Exception e)
{
//Error log
}
return res;
}
当我注意到在eager-loading而不是延迟加载时,在客户端显示请求的详细信息(在调用上面的函数之后)花了相当长的时间,我决定计时。
答案 0 :(得分:3)
这很有趣。实际上,加载加载较少的数据并不是真的。它会加载更多,因为您的所有包含都会合并到single enormous data set中。延迟加载的问题是每个延迟加载的属性导致额外的数据库查询=往返数据库。在您的本地计算机上可以超快,但是一旦您的数据库服务器位于网络的其他位置,它就会非常慢。
所以主要建议是:
答案 1 :(得分:1)
您目前正在将苹果与橙子进行比较:
db.ContextOptions.LazyLoadingEnabled = true;
request = db.requests.Where(rq => rq.idrequest == rID).FirstOrDefault();
这只是启用延迟加载,但加载本身尚未完成 - 在显式访问这些属性之前,尚未加载所有相关实体。
你说明的第二种情况会导致相应数据库表的连接,这自然比从一个表中取一行慢得多 - 但它会检索你需要的所有数据。