我可以做些什么来提高这个查询的速度?
What can I do to improve the speed of this query?
我有一个 linq 查询 returns 用户查看的最后一页基于 table 的页面点击率。这些字段只是 TimeStamp
、UserID
和 URL
,它们是从用户 activity 记录的。查询如下所示:
public static IQueryable GetUserStatus()
{
var ctx = new AppEntities();
var currentPageHits = ctx.Pagehits
.GroupBy(x => x.UserID)
.Select(x => x.Where(y => y.TimeStamp == x.Max(z => z.TimeStamp)))
.SelectMany(x => x);
return currentPageHits.OrderByDescending(o => o.TimeStamp);
}
查询运行完美,但运行缓慢。我们的 DBA 向我们保证 table 在所有正确的位置都有索引,问题一定出在查询上。
这有什么本质上的错误或不好吗,或者是否有更有效的方法来获得相同的结果?
你可以试试:
var currentPageHits2 = ctx.Pagehits
.GroupBy(x => x.UserID)
.Select(x => x.OrderByDescending(y => y.TimeStamp).First())
.OrderByDescending(x => x.TimeStamp);
不过速度应该是一样的。
请注意,此查询与您的查询之间存在细微差别...对于您的查询,如果 UserId 有两个 "max TimeStamp" PageHits 与相同的 TimeStamp,将返回两个 "rows",与此仅返回一个。
所以您尝试使用 LINQ 实现 DENSE_RANK() OVER (PARTITION BY UserID ORDER BY TimeStamp DESC)
?因此,根据 Timestamp
每个用户组的所有最新记录。你可以试试:
public static IQueryable GetUserStatus()
{
var ctx = new AppEntities();
var currentPageHits = ctx.Pagehits
.GroupBy(x => x.UserID)
.SelectMany(x => x.GroupBy(y => y.TimeStamp).OrderByDescending(g=> g.Key).FirstOrDefault())
.OrderByDescending(x => x.TimeStamp);
return currentPageHits;
}
因此它按 TimeStamp
对用户组进行分组,然后采用最新的组(一条或多条记录以防出现并列)。 SelectMany
将组合扁平化为记录。我认为这比您的查询更有效。
我有一个 linq 查询 returns 用户查看的最后一页基于 table 的页面点击率。这些字段只是 TimeStamp
、UserID
和 URL
,它们是从用户 activity 记录的。查询如下所示:
public static IQueryable GetUserStatus()
{
var ctx = new AppEntities();
var currentPageHits = ctx.Pagehits
.GroupBy(x => x.UserID)
.Select(x => x.Where(y => y.TimeStamp == x.Max(z => z.TimeStamp)))
.SelectMany(x => x);
return currentPageHits.OrderByDescending(o => o.TimeStamp);
}
查询运行完美,但运行缓慢。我们的 DBA 向我们保证 table 在所有正确的位置都有索引,问题一定出在查询上。
这有什么本质上的错误或不好吗,或者是否有更有效的方法来获得相同的结果?
你可以试试:
var currentPageHits2 = ctx.Pagehits
.GroupBy(x => x.UserID)
.Select(x => x.OrderByDescending(y => y.TimeStamp).First())
.OrderByDescending(x => x.TimeStamp);
不过速度应该是一样的。
请注意,此查询与您的查询之间存在细微差别...对于您的查询,如果 UserId 有两个 "max TimeStamp" PageHits 与相同的 TimeStamp,将返回两个 "rows",与此仅返回一个。
所以您尝试使用 LINQ 实现 DENSE_RANK() OVER (PARTITION BY UserID ORDER BY TimeStamp DESC)
?因此,根据 Timestamp
每个用户组的所有最新记录。你可以试试:
public static IQueryable GetUserStatus()
{
var ctx = new AppEntities();
var currentPageHits = ctx.Pagehits
.GroupBy(x => x.UserID)
.SelectMany(x => x.GroupBy(y => y.TimeStamp).OrderByDescending(g=> g.Key).FirstOrDefault())
.OrderByDescending(x => x.TimeStamp);
return currentPageHits;
}
因此它按 TimeStamp
对用户组进行分组,然后采用最新的组(一条或多条记录以防出现并列)。 SelectMany
将组合扁平化为记录。我认为这比您的查询更有效。