C# 如何优化此Linq查询以查找过去24小时内浏览量最多的博客帖子
我有一个博客网站,定期从Google Analytics检索每个博客文章的浏览量,并将其存储在数据库中。Blog表与ViewStats表具有一对多关系。ViewStats表简单存储日期和视图 两个相关表格如下:C# 如何优化此Linq查询以查找过去24小时内浏览量最多的博客帖子,c#,linq,asp.net-mvc-5,entity-framework-6,C#,Linq,Asp.net Mvc 5,Entity Framework 6,我有一个博客网站,定期从Google Analytics检索每个博客文章的浏览量,并将其存储在数据库中。Blog表与ViewStats表具有一对多关系。ViewStats表简单存储日期和视图 两个相关表格如下: | Blog | ViewStats | -----------+--------------| | Id | Id | | Title | Date | | Body | Views | |
| Blog | ViewStats |
-----------+--------------|
| Id | Id |
| Title | Date |
| Body | Views |
| | BlogId |
它是一个MVC网站,使用实体框架,在数据访问层中设置存储库
我想做的是获得过去24小时内浏览量最多的3篇博文。数据库中存储的所有视图都是累积的,因此我需要根据最近的结果减去24小时前的最后一个结果来排序每个博客文章
数据示例:
| Id | Date | Views | BlogId |
----------+------------------------------+-----------+------------|
| 1 | 2014-10-01 16:05:37.573 | 10 | 1 |
| 2 | 2014-10-01 16:05:37.573 | 8 | 2 |
| 3 | 2014-10-01 16:10:40.333 | 32 | 1 |
| 4 | 2014-10-01 16:10:40.333 | 12 | 2 |
这是我的疑问:
var query = blogRepo.GetBlogs()
.OrderByDescending(a =>
(a.ViewStats.OrderByDescending(v => v.Date)
.Select(v => v.Views)
.FirstOrDefault())
- (a.ViewStats.Where(v => v.Date < DateTime.Now.AddDays(-1))
.OrderByDescending(v => v.Date)
.Select(v => v.Views)
.FirstOrDefault()))
.Take(3);
var query=blogRepo.GetBlogs()
.OrderByDescending(a=>
(a.ViewStats.OrderByDescending(v=>v.Date)
.选择(v=>v.Views)
.FirstOrDefault())
-(a.ViewStats.Where(v=>v.Datev.Date)
.选择(v=>v.Views)
.FirstOrDefault())
.采取(3);
但是,它运行速度非常慢,现在ViewStats表中有大约10000行。有谁知道实现这一结果的更有效的方法吗
谢谢。如果在类中正确映射导航集合属性,则可以执行此操作。 还要确保GetBlogs方法返回IQueryable
// var blogs = blogRepo.GetBlogs();
var start = DateTime.Now.AddDays(-1);
var best =
from blog in blogs
let total = blog.Stats.Where(s => s.Date > start).Sum(i => i.Views)
orderby total descending
select new
{
blog, total
};
var results = best.Take(3);
此处的工作示例:
根据您的评论,您的
blogRepo.GetBlogs()
正在返回一个IEnumerable,该IEnumerable强制在内存中执行查询,而不是转换为SQL并针对数据库运行。这就是它慢的原因
使
GetBlogs()
返回一个IQueryable
,以利用数据库速度。不能在sql中完成任何(或全部)操作吗?@Jerrington如果OP使用EF,那么Linq查询将转换为sql。您考虑过做一个简单的分组方式吗?检查你的索引。你可以通过改变where子句来加速这个过程,这样就可以减少排序数据。也就是说,在最近发生的事件上放置一个where,以便它只获取数据库中过去15分钟内发生的记录。您还可以通过执行诸如where Date>Date-1 day之类的操作来交换24小时前的where和order by,并执行升序排序,而不是降序排序。确保您是针对IQueryable
而不是IEnumerable
进行查询。我特别关注GetBlogs()
。谢谢。将IQueryable更改为IQueryable就是解决方案。但是,为了使存储库只返回IEnumerable,我的高级开发人员建议将该方法放入存储库中的GetPopularBlogs(int numOfResults)中。非常感谢。很高兴听到这个消息,不过您应该只需要一个,因为您可以使用AsQueryable
和AsEnumerable
在两个接口之间来回切换。