总和
我有两列,name和name_searchable。我想搜索这些列(有数百万行)并根据匹配率返回结果。我有两个重要的标准;搜索应该是高效和快速的。我怎样才能做到这一点?
详情
我打算有一张包含数百万行的表格。所以基本上,我创建了一个转储表,只是为了测试一百万行的查询。该表使用MyISAM
存储引擎,它的索引和主键是id号。我想要进行的搜索涉及名称字段,即varchar
列。现在,基于查询,我想返回与查询部分或全部匹配的所有结果。因此,当用户搜索“björnborg”时,我想返回两者:
依旧......
这里的重要因素是=
运算符应始终返回比LIKE
运算符更高的排名。因此,'björnborg'应该始终出现在'bjorn borgus'之前。
最近,我问了关于如何以变音符号不敏感模式返回结果的问题,但不幸的是我无法使其工作。因此,我在名称列中创建了另一列,该列仅以英文字符存储名称。我们有name
和name_searchable
字段。
好吧,我用存储过程尝试了整个过程,但与普通查询相比,显然它确实很慢。因此,我想知道我是否可以根据匹配的where子句来排序结果。换句话说:
SELECT * FROM myUsers WHERE name = 'björn borg' OR name_searchable = 'bjorn borg' OR name LIKE '%björn borg%' OR name_searchable LIKE '%bjorn borg%';
所以基本上,这个想法是以不同的方式给每个条件一个得分点。我的意思是,虽然name ='björnborg'应该有等级,比方说5,name_searchable LIKE'%bjorn borg%'应该有2个(第二个4分,第三个3分......)我怎么能使用MySql使这项工作? (效率和速度是我的重要因素)
答案 0 :(得分:1)
如果不执行LIKE '%<text>%'
,您将获得更好的性能,因为这不会正确使用索引,而应使用LIKE '<text>%'
。我建议您考虑一下,如果您希望用户能够在查询花费很长时间并返回太多结果时搜索name_searchable LIKE '%s%'
以及相关的性能损失。
你试过吗
SELECT CASE WHEN name = 'björn borg' THEN 1
WHEN name_searchable = 'bjorn borg' THEN 2
WHEN name LIKE '%björn borg%' THEN 3
WHEN name_searchable LIKE '%bjorn borg%' THEN 4 ELSE 5 END AS rank, *
FROM myUsers
WHERE name = 'björn borg'
OR name_searchable = 'bjorn borg'
OR name LIKE '%björn borg%'
OR name_searchable LIKE '%bjorn borg%'
ORDER BY CASE WHEN name = 'björn borg' THEN 1
WHEN name_searchable = 'bjorn borg' THEN 2
WHEN name LIKE '%björn borg%' THEN 3
WHEN name_searchable LIKE '%bjorn borg%' THEN 4 ELSE 5 END
当然,最快的方法是添加LIMIT 1
另一种选择是在完全匹配失败时仅使用类似搜索:
SELECT CASE WHEN name = 'björn borg' THEN 1
WHEN name_searchable = 'bjorn borg' THEN 2
WHEN name LIKE '%björn borg%' THEN 3
WHEN name_searchable LIKE '%bjorn borg%' THEN 4 ELSE 5 END AS rank, *
FROM myUsers
WHERE name = 'björn borg'
OR name_searchable = 'bjorn borg'
OR (
NOT EXISTS (SELECT TOP 1 1 FROM myUsers WHERE name = 'björn borg' OR name_searchable = 'bjorn borg' )
AND (
OR name LIKE '%björn borg%'
OR name_searchable LIKE '%bjorn borg%'
)
)
ORDER BY CASE WHEN name = 'björn borg' THEN 1
WHEN name_searchable = 'bjorn borg' THEN 2
WHEN name LIKE '%björn borg%' THEN 3
WHEN name_searchable LIKE '%bjorn borg%' THEN 4 ELSE 5 END
答案 1 :(得分:0)
您是否考虑过分离查询和UNION
他们?
SELECT 5 AS rank, * FROM myUsers WHERE name = 'björn borg' UNION
SELECT 4 AS rank, * FROM myUsers WHERE name_searchable = 'bjorn borg' UNION
SELECT 3 AS rank, * FROM myUsers WHERE name LIKE '%björn borg%' UNION
SELECT 2 AS rank, * FROM myUsers WHERE name_searchable LIKE '%bjorn borg%'
ORDER BY 1 DESC