我有以下查询:
if (idUO > 0)
{
query = query.Where(b => b.Product.Center.UO.Id == idUO);
}
else if (dependencyId > 0)
{
query = query.Where(b => b.DependencyId == dependencyId );
}
else
{
var dependencyIds = dependencies.Select(d => d.Id).ToList();
query = query.Where(b => dependencyIds.Contains(b.DependencyId.Value));
}
[...] <- Other filters...
if (specialDateId != 0)
{
query = query.Where(b => b.SpecialDateId == specialDateId);
}
所以,我在这个查询中有其他过滤器,但最后,我用数据库处理查询:
return query.OrderBy(b => b.Date).Skip(20 * page).Take(20).ToList(); // the returned object is a Ticket object, that has 23 properties, 5 of them are relationships (FKs) and i fill 3 of these relationships with lazy loading
当我访问第一个page
时,确定,查询花费的时间少于1秒,但当我尝试访问页面30000时,查询花费的时间超过20秒。在linq查询中有一种方法,我可以提高查询的性能吗?或者只在数据库级别?而在数据库级别,对于这种查询,这是提高性能的最佳方法吗?
答案 0 :(得分:2)
这里没有太多的空间,imo,可以让事情变得更好(至少可以查看所提供的代码)。
当你试图在这些数字上取得良好的表现时,我建议你根本不要使用LINQ
,或者在列表中使用smaler数据访问的东西。
您可以在此处执行的操作是在DataBase
级别上引入该数据的分页,并使用一些stored procedure
,并从您的C#
代码中调用该数据。
答案 1 :(得分:1)
1-在DB中创建一个视图,按日期对项目进行排序,包括所有相关关系,如产品等。
2-创建一个存储过程,使用相关参数查询该视图。
答案 2 :(得分:1)
我建议您在运行查询时(快速和慢速)启动SQL Server Profiler,并在服务器上运行配置文件。 完成此操作后,您可以将其添加到数据库引擎优化顾问中,以获取有关您应添加的索引的一些提示。这对我来说过去有很大影响。当然,如果您知道需要哪些索引,只需添加它们而无需运行Advisor:)
答案 3 :(得分:0)
我认为您会发现数据库中存在瓶颈。这就是原因;
查询。
您有自己的查询和标准。它带有一个非常丑陋但不太可怕的选择语句进入数据库。
.OrderBy(b =&gt; b.Date)
现在你按日期订购了这个巨大的记录集,这可能不是一个糟糕的命中,因为它(希望)在该字段上被索引,但这确实意味着整个集合将被带入内存并在任何之前排序跳过或冒走。
.Skip(20 *页)。参加(20)
好的,这是糟糕的数据库变得粗糙的地方。对于大型记录集,实体对于这种事情非常可怕。我敢于你打开sql profiler并查看它发送的随机乱码sql。
当您开始跳过并采取时,实体通常会发送强制数据库的查询来扫描整个巨型记录集,直到找到您要查找的内容。如果这是记录集中的第一个有序记录,比如第1页,它可能不会花费非常长的时间。当你选择第30,000页时,由于实体准备你的陈述的方式,它可能会扫描大量数据。
我强烈建议您查看以下链接。我知道它说2005年,但它也适用于2008年。
http://www.codeguru.com/csharp/.net/net_data/article.php/c19611/Paging-in-SQL-Server-2005.htm
一旦您阅读了该链接,您可能需要考虑如何创建存储过程来完成您的目标。它将更轻量级,具有缓存的执行计划,并且非常有保证能够更快地为您返回数据。
除非你想坚持使用LINQ,否则请阅读Compiled Queries并确保将MergeOption.NoTracking设置为只读操作。您还应该尝试使用显式连接而不是具有延迟加载的IQueryable返回对象查询,尤其是在您迭代结果并加入其他表时。延迟加载可能是一个真正的性能杀手。