我有一个usersearch表,应该用于用户的快速子字符串搜索。此功能用于在键入用户名或名称时自动完成搜索。但是,我感兴趣的查询将只显示该用户所关注的用户的匹配项。
USERSEARCH
-----------------------------------------------
user_id(FK) username_ngram name_ngram
1 "AleBoy leBoy eBoy..." "Ale le e"
2 "craze123 raze123 ..." "Craze raze aze ze e"
3 "john1990 ohn1990 ..." "John ohn hn n"
4 "JJ_1 J_1 _1 1" "JJ"
USERRELATIONSHIP
-----------------------------------------------
user_id(FK) follows_id(FK)
2 1
2 3
以下查询是在某人刚键入“al”时执行的:
SELECT * FROM rage.usersearch where username_ngram like 'Al%' --1
UNION DISTINCT
SELECT * FROM rage.usersearch where name_ngram like 'Al%' --2
UNION DISTINCT
SELECT * FROM rage.usersearch --3
WHERE MATCH (username_ngram, name_ngram) AGAINST ('Al')
LIMIT 10
指数
index(user_id)
index(username_ngram)
index(name_ngram)
FULLTEXT(username_ngram, name_ngram)
有没有办法限制上面的查询只查看这个用户id子集(每个子查询不查询3次)?
SELECT follows_id FROM rage.userrelationship WHERE user_id={user_id of user doing the searching}
2条答案
按热度按时间7rfyedvj1#
mysql只能对每个表引用使用一个索引。它也可以只使用一个范围扫描每个索引。因此,无论是两列上的两个单独索引,还是两列上的一个复合索引,都不会阻止全表扫描。全文索引不适用于
LIKE
. 优化此查询的最佳方法是在联合查询中组合两个单独的搜索:发动机现在可以使用
INDEX(username_ngram)
对于第一个查询部分INDEX(name_ngram)
第二次。6tdlim6h2#
如果你要接收字符串的前几个字母,我看不出ngram的用处。
在这一点上,这是最佳的:
与
INDEX(name)
.如果你需要使用
UNION ALL
一起LIMIT
,然后执行以下操作:如果你不重复
LIMIT
每个子查询将收集所有相关的行,从而创建一个大于所需的临时表。如果你要用
OFFSET
(可能不适用于此应用程序),请参阅以下内容了解如何使其工作:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#or