我想知道我为统计编写的这个查询是否很快。目前,使用我在下面编写的数据和查询,它可以在 3 秒内运行。
现在我有一个用户表。角色为 Hr 的人可以创建空缺职位。所以用户有一个空缺列表。角色为候选人的用户可以申请这些职位空缺,并且该职位空缺存储在应用程序表中。所以有一个空缺的申请列表。现在我需要这样的统计数据:
我的数据库中的行号:
我的查询如下:
var statisticsQuery = _context.Users
.OrderBy(hrUser => hrUser.Id)
.Where(hrUser => hrUser.Roles.Any(p => p.RoleId == "Hr"))
.Select(hrUser => new VacancyByRecruiterModelDto
{
RecruiterId = hrUser.Id,
RecruiterFullName = hrUser.Name + " " + hrUser.Surname,
PublishedTotalVacancyCount = hrUser.Vacancies.Count(vac => vac.StatusId == 1),
CompletedTotalVacancyCount = hrUser.Vacancies.Count(vac => vac.StatusId == 2),
CvCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 1),
ExamCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 2),
InterviewCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 3),
DocumentCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 4),
HiringSuccessCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 5),
CvFailedCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 6),
CandidateFailedCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 7),
DontSeeCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 8),
ReserveCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 9),
InternCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 10),
SecurityCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 11),
DontExamCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 12),
DontInterviewCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 13),
HiringStoppedCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 14),
FailInternshipCount = hrUser.Vacancies
.SelectMany(vac => vac.Applications)
.Count(app => app.StatusId == 15),
}).AsNoTracking();
if (loadMore?.Skip != null && loadMore?.Take != null)
{
statisticsQuery = statisticsQuery.Skip(loadMore.Skip.Value).Take(loadMore.Take.Value);
}
现在,当我设置 Take 10 并仅查询 10 小时用户时,上述代码在 3 秒内运行。这是正常现象还是应该进一步优化?如果应该做的话,怎么做?
您可以考虑更新 DTO,将应用程序计数存储为由 EF/Linq 填充的分组,然后公开特定计数的帮助器属性:
public class VacancyByRecruiterModelDto
{
public int RecruiterId { get; set; }
public string RecruiterFullName { get; set;}
public int PublishedTotalVacancyCount { get; set; }
public int CompletedTotalVacancyCount { get; set; }
public Dictionary<int, int> ApplicationCounts { get; set; } = new();
public int CvCount
{
int count = 0;
ApplicationCounts.TryGetValue(1, out count);
return count;
// You could use ApplicationCounts[1], however if no item in the user
// has a status of 1 there would be no element /w count.
}
public int ExamCount
{
int count = 0;
ApplicationCounts.TryGetValue(2, out count);
return count;
}
// ... repeat for each count...
}
然后填充时:
var statisticsQuery = _context.Users
.OrderBy(hrUser => hrUser.Id)
.Where(hrUser => hrUser.Roles.Any(p => p.RoleId == "Hr"))
.Select(hrUser => new VacancyByRecruiterModelDto
{
RecruiterId = hrUser.Id,
RecruiterFullName = hrUser.Name + " " + hrUser.Surname,
PublishedTotalVacancyCount = hrUser.Vacancies.Count(vac => vac.StatusId == 1),
CompletedTotalVacancyCount = hrUser.Vacancies.Count(vac => vac.StatusId == 2),
ApplicationCounts = hrUser.Vacancies
.SelectMany(v => v.Applications)
.GroupBy(a => a.StatusId)
.ToDictionary(g => g.Key, g.Count())
});
if (loadMore?.Skip != null && loadMore?.Take != null)
{
statisticsQuery = statisticsQuery
.Skip(loadMore.Skip.Value)
.Take(loadMore.Take.Value);
}
同样,如果有可能存在两种以上的状态,则可以对空缺计数执行此操作。请注意,仅在加载实体时才需要
AsNoTracking
。投影时不需要/使用。