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 查询执行时间过长。需要提高查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

MaxComputeSql性能调优

在提高 SQL Query 的查询性能方面需要帮助

如何提高查询性能?

如何提高 SQL Azure 查询性能

# Sql语句过长报错查询慢优化方案探索

如何提高sql中的查询性能?