如果未找到搜索项,SQL查询将继续运行很长时间
在我的Azure托管ASP.NET核心站点中,我有一个用户表,我实现了如下搜索:如果未找到搜索项,SQL查询将继续运行很长时间,sql,sql-server,linq,linq-to-sql,asp.net-core,Sql,Sql Server,Linq,Linq To Sql,Asp.net Core,在我的Azure托管ASP.NET核心站点中,我有一个用户表,我实现了如下搜索: var inner = from user in db.Users select new { Name = user.Name, Verified = user.Verified, PhotoURL = user.PhotoURL,
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语句:
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秒)。
当我们将此功能发布到internet时,这会极大地影响性能
你能提出一个解决这个问题的办法吗
多谢各位
更新:此问题在此继续:您已经可以这样简化查询;):
如果存在性能问题,请尝试使用SQL创建存储过程,并将其与实体框架一起使用。您已经可以这样简化查询;):
如果存在性能问题,请尝试使用SQL创建存储过程,并将其与entity Framework一起使用。SQL Server必须使用扫描来查找与.Contains子句匹配的行。这是没有办法的 但是,如果我们减少SQL server必须扫描的数据量,我们将加快查询速度 覆盖过滤指数 如果索引包含查询中需要返回的所有数据,那么它就是“覆盖”
CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name])
INCLUDE ( [PhotoURL], [Id], [Subdomain], [Deleted], [AppearInSearch] )
WHERE [AppearInSearch]=1 AND [Deleted]=0
此索引可能比原始表小得多,因此即使需要扫描,也会更快
根据生成的计划,此索引可能是更好的选择。它不包括额外的列,将更小。需要进行测试以确定最佳选择
CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name])
WHERE [AppearInSearch]=1 AND [Deleted]=0
SQL Server必须使用扫描来查找与.Contains子句匹配的行。这是没有办法的 但是,如果我们减少SQL server必须扫描的数据量,我们将加快查询速度 覆盖过滤指数 如果索引包含查询中需要返回的所有数据,那么它就是“覆盖”
CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name])
INCLUDE ( [PhotoURL], [Id], [Subdomain], [Deleted], [AppearInSearch] )
WHERE [AppearInSearch]=1 AND [Deleted]=0
此索引可能比原始表小得多,因此即使需要扫描,也会更快
根据生成的计划,此索引可能是更好的选择。它不包括额外的列,将更小。需要进行测试以确定最佳选择
CREATE INDEX IX_User_Name_filtered ON USER ([Verified], [Name])
WHERE [AppearInSearch]=1 AND [Deleted]=0
您是否看过运行时间较长的实例的解释计划?我猜该列已编制索引,但未应用NOTNULL约束。如果是这样,请尝试应用NOTNULL约束,用“UNKNOWN”之类的神奇字符串替换现有的NULL。@KevinPostlewaite事实上它是一个NOTNULL列。如果该项可用,执行就不是问题。嗯,听起来好像是在做一个完整的表扫描,以防在索引中找不到该项,而该项根本不存在。您使用的是标准的btree索引还是其他类型的索引?如果找不到术语,您能得到实际执行路径吗?您是否使用EXPLAIN PLAN来确认它使用的是您期望的索引?它只对已验证的而不是名称使用索引,因为它是LINQ@kevinpostlewaited中的Contain()方法。您在执行同步查询时也会遇到同样的问题(ToList()而不是ToListSync(),并且没有等待)?您是否看过运行时间较长的实例的解释计划?我猜该列已编制索引,但未应用NOTNULL约束。如果是这样,请尝试应用NOTNULL约束,用“UNKNOWN”之类的神奇字符串替换现有的NULL。@KevinPostlewaite事实上它是一个NOTNULL列。如果该项可用,执行就不是问题。嗯,听起来好像是在做一个完整的表扫描,以防在索引中找不到该项,而该项根本不存在。您使用的是标准的btree索引还是其他类型的索引?如果找不到术语,您能得到实际执行路径吗?您是否使用EXPLAIN PLAN来确认它使用的是您期望的索引?它只对已验证的而不是名称使用索引,因为它是LINQ@kevinpostlewaited中的一个Contain()方法。当您执行同步查询(ToList()而不是ToListSync(),并且没有等待)时,您是否也会遇到同样的问题?谢谢。这与此类似,但MS支持人员建议只查询固定长度的列。谢谢。这与此类似,但MS Support建议只查询固定长度的列。我们尝试了类似的方法,请参见:您是否尝试添加上述索引?您提到的另一个问题是此查询执行不佳的症状。首先解决这个问题,另一个问题就不成问题了。我今天早上已经解决了。这个问题变得非常奇怪,我尝试了许多索引。我们也尝试了类似的方法,请参见:您是否尝试添加上述索引?您提到的另一个问题是此查询执行不佳的症状。先解决这个问题,另一个问题就不成问题了。我今天早上已经解决了。这个问题变得非常奇怪,我尝试了很多索引。