mysql搜索where子句,每个条件具有不同的分数
总之 我有两列,name和name\u searchable。我想搜索这些列(有数百万行),并根据它们的匹配率返回结果。我有两个重要的标准;搜索应该是高效和快速的。我怎样才能做到这一点 详细信息 我计划有一张有数百万行的桌子。所以基本上,我创建了一个转储表,只是为了用一百万行测试查询。该表使用的是mysql搜索where子句,每个条件具有不同的分数,mysql,performance,search,Mysql,Performance,Search,总之 我有两列,name和name\u searchable。我想搜索这些列(有数百万行),并根据它们的匹配率返回结果。我有两个重要的标准;搜索应该是高效和快速的。我怎样才能做到这一点 详细信息 我计划有一张有数百万行的桌子。所以基本上,我创建了一个转储表,只是为了用一百万行测试查询。该表使用的是MyISAM存储引擎,它的索引和主键是id号。我要进行的搜索与name字段有关,该字段是varchar列。现在,基于一个查询,我想返回与查询部分或全部匹配的所有结果。因此,当用户搜索“björn bor
MyISAM
存储引擎,它的索引和主键是id号。我要进行的搜索与name字段有关,该字段是varchar
列。现在,基于一个查询,我想返回与查询部分或全部匹配的所有结果。因此,当用户搜索“björn borg”时,我想返回两个:
- 比约恩博格
- 比约恩·博格斯
- 比约恩·博格(注意o)
=
操作符应该总是返回比LIKE
操作符更高的排名。因此,“比约恩·博格”应该总是排在“比约恩·博格斯”之前
最近,我问了一个关于如何在不区分发音的模式下返回结果的问题,但不幸的是,我无法让它工作。因此,我沿着name列创建了另一列,该列仅以英文字符存储名称。因此,我们有name
和name\u 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örn borg'应该有排名,比如说,5,但是像'%bjorn borg%'一样的name_searchable应该有2(第二个是4分,第三个是3分……),我如何使用MySql实现这一点?(效率和速度对我来说很重要)您是否考虑过将查询分离并
合并它们
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
如果不像“%”
那样执行操作,您将获得更好的性能,因为这样做不会正确使用索引,而应该像“%”
那样使用。我建议您考虑,如果您希望用户能够搜索“代码> NAMEX”,比如“%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
另一种选择是仅在精确匹配失败时使用like搜索:
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
您最好运行多个独立的查询,而不是尝试在一个查询中运行。where子句不是进行此类计算的好地方。如果我错了,请纠正我,但这是否意味着要搜索整个表4次?换句话说,对于10万条记录,这就像搜索40万条记录。还是mysql缓存了第一条select语句,事情处理得更快了?这不像搜索4000万条记录,因为如果您的表中有4000万条记录,那么该表上的索引将大大增加。我不是MySQL内部的专家。它们可能作为单独的查询执行,但相关数据可能会保存在内存中,直到所有查询完成。