簡體   English   中英

Linq 查詢慢,計數。 SQL 查詢速度非常快。 我究竟做錯了什么?

[英]Linq Query slow with Count. SQL query is very fast. What am I doing wrong?

我有一個非常基本的親子關系。 對於我的主頁,我只想從 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()
};

現在展平的總行數約為 1000,這大約需要 10 秒才能完成。 如果我寫一個 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'

這需要不到一秒鍾的時間來完成。

我認為我的問題出在 linq COUNT 部分。 我試過做一個子查詢,但仍然很慢。 我認為問題在於 linq 查詢將所有數據帶到客戶端並在客戶端完成所有工作,而不是讓服務器完成所有工作?

有一個更好的方法嗎?

編輯:我正在使用實體框架,當我檢查 SQL 分析器時,SQL 發送非常長且復雜。

實體框架(就像任何其他程序化 Object 關系映射器一樣)的性能和效率越差,您的請求越復雜。

所以,選項:

  1. 處理它。 嗯,這不是最好的。 顯然它會很慢,但如果它起作用,它就會起作用。
  2. 在 EF EF6 / core中使用 Raw SQL 查詢。
  3. 使用不同的 ORM,但您需要自己評估這些以找出優缺點。
  4. Forgo SQL in c# entirely and use Stored Procedures, View, Functions, and other SQL objects to keep SQL queries in the database. (感謝Antonín Lejsek

這里的問題是,您編寫了非等效的 LiNQ 查詢。 在投影中沒有最佳預測如何處理FirstOrDefault 它會創建額外的 OUTER APPLY 連接,但速度很慢。

重寫您的查詢,使其盡可能接近 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM