SQL 查询执行时间过长。需要提高查询的性能
Posted
技术标签:
【中文标题】SQL 查询执行时间过长。需要提高查询的性能【英文标题】:SQL query takes too long to execute. Need to improve performance of query 【发布时间】:2022-01-06 06:54:42 【问题描述】:我正在使用 SQL Server、.NET 5 环境。此 SQL 查询执行时间过长。这个查询等待时间几乎是 3 分钟,但只有 35 条记录。有没有更好的方法来优化这个查询?
var allmeetings = await _context.MeetingMaster
.Where(x => x.IsActive == true &&
(x.MeetingParticipants.Any(y => y.ParticipantId == Convert.ToInt32(_currentUserService.CurrentUserId)) ||
x.OrganizedById == Convert.ToInt32(_currentUserService.CurrentUserId)))
.Include(a => a.MeetingParticipants)
.ThenInclude(b => b.Participant)
.Include(a => a.MeetingAgendaItems)
.ThenInclude(e => e.MeetingActionItems)
.ThenInclude(w => w.ActionItemLogs)
.Include(a => a.MeetingAgendaItems)
.ThenInclude(e => e.MeetingActionItems)
.ThenInclude(w => w.ActionItemResposibilities)
.Include(g => g.MeetingAgendaItems)
.ThenInclude(v => v.MeetingAgendaItemTypes)
.ThenInclude(j => j.AgendaItemRef)
.Include(w => w.MeetingAgendaItems)
.ThenInclude(d => d.RestrictedAgendaItemList)
.ThenInclude(s => s.ParticipantRef)
.Include(s => s.MeetingAgendaItems)
.ThenInclude(q => q.MeetingAgendaItemSupportiveDocuments)
.Include(c => c.MonthsRef)
.Include(z => z.YearsRef)
.Include(g => g.MeetingMinutesDoc)
.Include(c => c.Project)
.Include(c => c.Category)
.Include(l => l.MeetingSuggestions)
.Include(q => q.MeetingMattersArises)
.ThenInclude(i => i.MattersAriseResponsibilities)
.ThenInclude(s => s.ResponsiblePerson)
.Include(e => e.MeetingMattersArises)
.ThenInclude(w => w.MattersAriseReviewerComments)
.Include(s => s.MeetingMattersArises)
.ThenInclude(e => e.MattersAriseLogs)
.AsSplitQuery()
.ToListAsync(cancellationToken);
var result = allmeetings.Where(x => x.IsActive == true &&
x.isRecurringMeeting == false &&
(x.MeetingParticipants.Any(y => y.ParticipantId == Convert.ToInt32(_currentUserService.CurrentUserId)) || x.OrganizedById == Convert.ToInt32(_currentUserService.CurrentUserId))).ToList();
var RecMeetings = allmeetings.Where(x => x.IsActive == true &&
x.isRecurringMeeting == true &&
(x.MeetingParticipants.Any(y => y.ParticipantId == Convert.ToInt32(_currentUserService.CurrentUserId)) || x.OrganizedById == Convert.ToInt32(_currentUserService.CurrentUserId))).ToList();
var groupedRecMeetings = RecMeetings.GroupBy(u => u.MeetingRefId.Substring(0, u.MeetingRefId.LastIndexOf('-'))).Select(grp => grp.ToList()).ToList();
var GraeterMeetings = new List<MeetingMaster>();
foreach (var met in groupedRecMeetings)
result.AddRange(met.FindAll(x => x.MeetingStatus != "Initiated" ));
GraeterMeetings.AddRange(met.FindAll(x => x.MeetingStatus == "Initiated"));
if(GraeterMeetings.Count != 0)
result.Add(GraeterMeetings.OrderBy(x => x.MeetingDate).First());
GraeterMeetings.Clear();
return result.OrderByDescending(d => d.Id).ToList();
【问题讨论】:
请发布正在运行的确切 SQL 查询。如前所述,尚不清楚过滤条件是什么(WHERE
)或行顺序是什么(ORDER BY
)。
16 (!!!!) .Include
和 14 .ThenInclude
- 你很惊讶它需要“很长时间”来收集数据!?! ?!?!?!
所有ToList
可能也无济于事。他们为什么在那里?
35 条记录,但可能有 16 + 14 条连接??你肯定需要所有这些吗?
这里是拆分查询,所以 30 个单独的查询,都带有连接和过滤器。
【参考方案1】:
首先,你有这么多的 Includes() 和 ThenIncludes(),如果这对你的性能真的很不利的话。有没有办法可以减少这些包括 -> 只使用必要的。
那么我希望您在语句末尾执行 .ToList() 查询(在您返回之前)
下面是我过去的示例(使用分页和过滤):
var context = _context.People
.Include(x => x.Parents)
.ThenInclude(x => x.Adress)
.Include(x => x.Job)
.Include(x => x.Hobbies);
var items = string.IsNullOrWhiteSpace(query)
? context
: context.Where(x => x.Name.Contains(query));
var filters = new List<int>();
if (filter != null)
filters = filter.Split(',').Select(int.Parse).ToList();
items = items.Where(x => x.Parents.Select(s => s.AdressId).Any(z => filters.Any(y => y == z)));
return await items.Skip(page * take).Take(take).ToListAsync();
【讨论】:
以上是关于SQL 查询执行时间过长。需要提高查询的性能的主要内容,如果未能解决你的问题,请参考以下文章