我们有一个asp.net核心网站,用于处理用户搜索,如下所示:
public async Task<ICollection<UserSearchResult>> SearchForUser(string name, int page)
{
return await db.ApplicationUsers.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.Id,
Subdomain = u.Subdomain
}).ToListAsync();
}
查询转换为类似于以下内容的内容:
SELECT [t].[Name], [t].[Verified], [t].[PhotoURL], [t].[Id], [t].[Subdomain] FROM (SELECT [u0].* FROM [AspNetUsers] AS [u0] WHERE (((CHARINDEX('khaled', [u0].[Name]) > 0) OR ('khaled' = N'')) AND ([u0].[Deleted] = 0)) AND ([u0].[AppearInSearch] = 1) ORDER BY [u0].[Verified] DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY ) AS [t]
在客户端,我们使用typeahead和bloodhound如下:
engine = new Bloodhound({
identify: function (user) {
return user.UserID;
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
dupDetector: function (a, b) { return a.UserID === b.UserID; },
remote: {
cache: false,
url: '/account/Search?name=%QUERY&page=0',
wildcard: '%QUERY'
}
});
我们按如下方式配置typeahead:
$('#demo-input').typeahead(
{
hint: $('.Typeahead-hint'),
menu: $('.Typeahead-menu'),
minLength: 3,
classNames:
{
open: 'is-open',
empty: 'is-empty',
cursor: 'is-active',
suggestion: 'Typeahead-suggestion',
selectable: 'Typeahead-selectable'
}
},
{
source: engineWithDefaults,
displayKey: 'name',
templates:
{
suggestion: template,
empty: empty,
footer: all
},
limit: 5
})
搜索只能在localhost上找到,并且查询作为sql查询运行良好。 我还创建了一个已验证的索引,并将速度降低到1秒或更短。
我们的网站拥有数百万注册用户,问题是只要我们为所有用户提供搜索,Azure上的DTU百分比就会达到100%并且查询会超时。 我们还有一个redis缓存来加速类似的查询,但这对我们没有帮助解决这个问题。
感谢您的支持:)
答案 0 :(得分:0)
它很可能是u.Name.Contains(name)
,即CHARINDEX('khaled', [u0].[Name]) > 0
,它必须扫描整个表格,或者最好是扫描索引。这将是缓慢的,你可以做的不多。
如果您对deleted
或appearInSearch
有较大的偏见,则可能会使用条件索引,但这些类型的搜索速度非常慢。你需要一些特殊的结构来实现这个目的。