mysql搜索where子句,每个条件具有不同的分数

时间:2011-10-11 20:53:08

标签: mysql performance search

总和

我有两列,name和name_searchable。我想搜索这些列(有数百万行)并根据匹配率返回结果。我有两个重要的标准;搜索应该是高效和快速的。我怎样才能做到这一点?

详情

我打算有一张包含数百万行的表格。所以基本上,我创建了一个转储表,只是为了测试一百万行的查询。该表使用MyISAM存储引擎,它的索引和主键是id号。我想要进行的搜索涉及名称字段,即varchar列。现在,基于查询,我想返回与查询部分或全部匹配的所有结果。因此,当用户搜索“björnborg”时,我想返回两者:

  • björnborg
  • björnborgus
  • bjorn borg(注意o)

依旧......

这里的重要因素是=运算符应始终返回比LIKE运算符更高的排名。因此,'björnborg'应该始终出现在'bjorn borgus'之前。

最近,我问了关于如何以变音符号不敏感模式返回结果的问题,但不幸的是我无法使其工作。因此,我在名称列中创建了另一列,该列仅以英文字符存储名称。我们有namename_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使这项工作? (效率和速度是我的重要因素)

2 个答案:

答案 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