我有一个运行速度非常快的以下查询:
var query =
(from art in ctx.Articles
join phot in ctx.ArticlePhotos on art.Id equals phot.ArticleId
join artCat in ctx.ArticleCategories on art.Id equals artCat.ArticleId
join cat in ctx.Categories on artCat.CategoryId equals cat.Id
where art.Active && art.ArticleCategories.Any(c => c.Category.MaterializedPath.StartsWith(categoryPath))
orderby art.PublishDate descending
select new ArticleSmallResponse
{
Id = art.Id,
Title = art.Title,
Active = art.Active,
PublishDate = art.PublishDate ?? art.CreateDate,
MainImage = phot.RelativePath,
RootCategory = art.Category.Name,
Summary = art.Summary
})
.AsNoTracking().Take(request.Take);
但是,如果我添加
group by
并将查询更改为以下语句,它的运行速度会慢得多。
var query =
(from art in ctx.Articles
join phot in ctx.ArticlePhotos on art.Id equals phot.ArticleId
join artCat in ctx.ArticleCategories on art.Id equals artCat.ArticleId
join cat in ctx.Categories on artCat.CategoryId equals cat.Id
where art.Active && art.ArticleCategories.Any(c => c.Category.MaterializedPath.StartsWith(categoryPath))
orderby art.PublishDate descending
select new ArticleSmallResponse
{
Id = art.Id,
Title = art.Title,
Active = art.Active,
PublishDate = art.PublishDate ?? art.CreateDate,
MainImage = phot.RelativePath,
RootCategory = art.Category.Name,
Summary = art.Summary
})
.GroupBy(m => m.Id)
.Select(m => m.FirstOrDefault())
.AsNoTracking().Take(request.Take);
每个类别首页调用查询9次。使用第一个版本的查询,在没有打开缓存并远程连接到 SQL 的情况下,页面加载时间约为 1.5 秒,这使得当应用程序位于服务器上时几乎是即时的,但第二种方式使得当 SQL 远程时主页加载时间约为 39 秒。
是否可以在不将整个查询重写到视图或存储过程中的情况下修复它?
分组是数据库端一项昂贵的操作。如果不知道您的数据库是什么样子以及您设置了哪些索引,则很难确定。为什么不在数据到达后在客户端进行分组(假设数据量不是很大)。
这个问题解释了如何做。 LINQ 中的分组依据
始终建议向 GroupBy 列添加索引。另外,为 where 子句中使用的列添加索引。