如果未找到搜索词,SQL 查询会继续运行很长时间 [英] SQL Query continues running for a very long time if search term not found

查看:25
本文介绍了如果未找到搜索词,SQL 查询会继续运行很长时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Azure 托管 ASP.NET Core 站点中,我有一个用户表,并按如下方式实现了搜索:

In my Azure hosted ASP.NET Core site I have a table of users and I implemented search as follows:

    var inner = from user in db.Users
             select  new
             {
                 Name = user.Name,
                 Verified = user.Verified,
                 PhotoURL = user.PhotoURL,
                 UserID = user.Id,
                 Subdomain = user.Subdomain,
                 Deleted=user.Deleted,
                 AppearInSearch = user.AppearInSearch
             };
    return await inner.Where(u=>u.Name.Contains(name)&& !u.Deleted && u.AppearInSearch)
                                    .OrderByDescending(u => u.Verified)
                                    .Skip(page * recordsInPage)
                                    .Take(recordsInPage)
                                    .Select(u => new UserSearchResult()
                                    {
                                        Name = u.Name,
                                        Verified = u.Verified,
                                        PhotoURL = u.PhotoURL,
                                        UserID = u.UserID,
                                        Subdomain = u.Subdomain
                                    }).ToListAsync();

这将转换为类似于以下内容的 SQL 语句:

This translates to a SQL statement similar to the following:

SELECT [t].[Name], [t].[Verified],
       [t].[PhotoURL], [t].[Id], 
       [t].[Subdomain], [t].[Deleted], 
       [t].[AppearInSearch]  
FROM (      
        SELECT [user0].[Name], [user0].[Verified], 
               [user0].[PhotoURL], [user0].[Id], 
               [user0].[Subdomain], [user0].[Deleted], 
               [user0].[AppearInSearch]      
        FROM [AspNetUsers] AS [user0]
        WHERE (((CHARINDEX('khaled', [user0].[Name]) > 0) OR ('khaled' = N'')) 
          AND ([user0].[Deleted] = 0)) 
          AND ([user0].[AppearInSearch] = 1)      
        ORDER BY [user0].[Verified] DESC      
        OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY  ) AS [t]

如果搜索词在数据库中可用,则在不到一秒的时间内获得结果.但是,如果查询运行很长时间没有找到(我见过一次达到 48 秒).

If the search term is available in the database, the result is obtained in less than a second. However, If it's not found the query runs for a very long time (I have seen it once reaching 48 seconds).

当我们将此功能发布到互联网时,这会极大地影响性能.

This greatly affects performance when we publish this feature to the internet.

您能否提出解决此问题的方法?

Can you kindly suggest a way to solve this issue?

谢谢

更新:此问题在此处继续:显示系统时出现空登录名.进程

Update: this issue is continued here: Empty Login Name When Showing sys.processes

推荐答案

SQL Server 必须使用扫描来查找与 .Contains 子句匹配的行.没有办法解决这个问题.

SQL Server has to use a scan to find rows matching the .Contains clause. There is no way around this.

但是,如果我们减少 SQL Server 必须扫描的数据量,我们将加快查询速度.

However, if we reduce the amount of data that SQL server has to scan, we will speed up the query.

如果索引包含查询中需要返回的所有数据,则它是覆盖"的.

An index is "covering" if it contains all the data needed to be returned in a query.

CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name]) 
INCLUDE ( [PhotoURL], [Id], [Subdomain], [Deleted], [AppearInSearch]  ) 
WHERE [AppearInSearch]=1 AND [Deleted]=0

这个索引可能比原始表小很多,所以即使需要扫描,它也会更快.

This index is likely substantially smaller than the original table, so even if a scan is required, it will be quicker.

根据生成的计划,此索引可能是更好的选择.它不包括额外的列并且会更小.需要进行测试以确定最佳选择.

Depending on the plan that is generated, this index may be a better choice. it doesn't include the extra columns and will be smaller still. Testing will be required to determine the best choice.

CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name]) 
WHERE [AppearInSearch]=1 AND [Deleted]=0

这篇关于如果未找到搜索词,SQL 查询会继续运行很长时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆