在我的Azure托管的ASP.NET核心站点中,我有一个用户表,我按如下方式实现了搜索:
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秒)。
当我们将此功能发布到互联网时,这会极大地影响性能。
您能否提出解决此问题的方法?
谢谢
更新:此问题在此处继续:Empty Login Name When Showing sys.processes
答案 0 :(得分:0)
您已经可以像这样简化查询;):
int start=page * recordsInPage;
var inner = (from user in db.Users
where user.Name.Contains(name) && !user.Deleted && user.AppearInSearch
orderby user.Verified descending
select new
{
Name = user.Name,
Verified = user.Verified,
PhotoURL = user.PhotoURL,
UserID = user.Id,
Subdomain = user.Subdomain,
Deleted=user.Deleted,
AppearInSearch = user.AppearInSearch
}
).Skip(start).Take(recordsInPage);
return await inner.ToListAsync();
如果遇到性能问题,请尝试使用SQL创建存储过程并将其与实体框架一起使用。
答案 1 :(得分:0)
SQL Server必须使用扫描来查找与.Contains子句匹配的行。没有办法解决这个问题。
但是,如果我们减少SQL服务器必须扫描的数据量,我们将加快查询速度。
索引是"覆盖"如果它包含查询中需要返回的所有数据。
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