[英]Linq Query slow with Count. SQL query is very fast. What am I doing wrong?
I have a very basic parent children relationship.我有一个非常基本的亲子关系。 For my main page, I just wanted to get the counts from the children table.对于我的主页,我只想从 children 表中获取计数。
var assignmenTotal = new AssignmentUser
{
IsSupervisor = supervisor,
AssignmentTotals = (
from a in db.Assignments
where (StartDate.HasValue)
? DbFunctions.TruncateTime(a.CreatedDate) == StartDate
: a.IsArchived == false
orderby a.ID ascending
join b in db.Adjustments on a.ID equals b.AssignmentID
group b by new {a.ID,a.UserName,a.Status,a.CreatedDate,a.IsArchived}
into g
select new AssignmentTotals
{
ID = g.Key.ID,
UserName = g.Key.UserName,
Status = g.Key.Status,
ImportedDate = DbFunctions.TruncateTime(g.Key.CreatedDate),
StartingLocation = (db.Adjustments
.Where(x => x.AssignmentID == g.Key.ID)
.OrderBy(x => x.LocationID)
.Select(x => x.LocationID)
.FirstOrDefault()),
EndingLocation = (db.Adjustments.
Where(x => x.AssignmentID == g.Key.ID)
.OrderByDescending(x => x.LocationID)
.Select(x => x.LocationID)
.FirstOrDefault()),
TotalLocations = g.Count(x => x.LocationID != null),
TotalLicensePlates = g.Count(x => x.ExpectedLicensePlateID != null),
TotalAdjCompleted = g.Count(x => x.Status == "C"),
IsSameUser = (currUser == g.Key.UserName ? true : false),
IsArchived = g.Key.IsArchived
})
.OrderBy(x => x.ID)
.ToList()
};
Now total flatten rows are about 1000 and this is taking about 10 seconds to complete.现在展平的总行数约为 1000,这大约需要 10 秒才能完成。 If I write a SQL Query如果我写一个 SQL 查询
SELECT ID, UserName, Status, b.StartLocation, b.EndLocation, b.TotalLocations,
b.TotalLicensePlates, b.TotalLocations
FROM Assignments a
INNER JOIN(
SELECT AssignmentID,
min(LocationID) as StartLocation, max(LocationID) as EndLocation,
COUNT(CASE WHEN LocationID is NOT NULL THEN 1 ELSE 0 end) AS TotalLocations,
SUM(CASE WHEN ExpectedLicensePlateID IS NOT NULL THEN 1 ELSE 0 END )TotalLicensePlates,
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END )TotalAdjCompleted
FROM dbo.Adjustments
group by AssignmentID
) b on (a.ID = b.AssignmentID)
WHERE convert(date,a.CreatedDate) ='04/23/2021'
This takes less than a second to complete.这需要不到一秒钟的时间来完成。
I think my problem is in the linq COUNT part.我认为我的问题出在 linq COUNT 部分。 I have tried doing a subquery but is still slow.我试过做一个子查询,但仍然很慢。 I think the problem is that the linq query is bringing all the data to client and doing all the work in the client instead of having the server doing all the work?我认为问题在于 linq 查询将所有数据带到客户端并在客户端完成所有工作,而不是让服务器完成所有工作?
Is there a better way to do this?有一个更好的方法吗?
Edit: I'm using Entity Framework and when I checked the SQL profiler, the SQL send is very long and complicated.编辑:我正在使用实体框架,当我检查 SQL 分析器时,SQL 发送非常长且复杂。
Entity Framework (just like any other programmatic Object Relational Mapper) get worse performance and efficient the more complex your request is.实体框架(就像任何其他程序化 Object 关系映射器一样)的性能和效率越差,您的请求越复杂。
So, options:所以,选项:
Problem here, that you have written non equivalent LiNQ Query.这里的问题是,您编写了非等效的 LiNQ 查询。 There is no optimal prediction what to do with FirstOrDefault
in projection.在投影中没有最佳预测如何处理FirstOrDefault
。 It creates additional OUTER APPLY joins which is slow.它会创建额外的 OUTER APPLY 连接,但速度很慢。
Rewrite your query to be closer to the SQL as possible:重写您的查询,使其尽可能接近 SQL:
var query =
from a in db.Assignments
where (StartDate.HasValue)
? DbFunctions.TruncateTime(a.CreatedDate) == StartDate
: a.IsArchived == false
orderby a.ID ascending
join b in db.Adjustments on a.ID equals b.AssignmentID
group b by new {a.ID,a.UserName,a.Status,a.CreatedDate,a.IsArchived}
into g
select new AssignmentTotals
{
ID = g.Key.ID,
UserName = g.Key.UserName,
Status = g.Key.Status,
ImportedDate = DbFunctions.TruncateTime(g.Key.CreatedDate),
StartingLocation = g.Min(x => x.LocationID)
EndingLocation = g.Max(x => x.LocationID),
TotalLocations = g.Count(x => x.LocationID != null),
TotalLicensePlates = g.Count(x => x.ExpectedLicensePlateID != null),
TotalAdjCompleted = g.Count(x => x.Status == "C"),
IsSameUser = (currUser == g.Key.UserName ? true : false),
IsArchived = g.Key.IsArchived
};
var totals = query
.OrderBy(x => x.ID)
.ToList();
var assignmenTotal = new AssignmentUser
{
IsSupervisor = supervisor,
AssignmentTotals = totals
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.