Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mysql搜索where子句,每个条件具有不同的分数_Mysql_Performance_Search - Fatal编程技术网

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

mysql搜索where子句,每个条件具有不同的分数,mysql,performance,search,Mysql,Performance,Search,总之 我有两列,name和name\u searchable。我想搜索这些列(有数百万行),并根据它们的匹配率返回结果。我有两个重要的标准;搜索应该是高效和快速的。我怎样才能做到这一点 详细信息 我计划有一张有数百万行的桌子。所以基本上,我创建了一个转储表,只是为了用一百万行测试查询。该表使用的是MyISAM存储引擎,它的索引和主键是id号。我要进行的搜索与name字段有关,该字段是varchar列。现在,基于一个查询,我想返回与查询部分或全部匹配的所有结果。因此,当用户搜索“björn bor

总之

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

详细信息

我计划有一张有数百万行的桌子。所以基本上,我创建了一个转储表,只是为了用一百万行测试查询。该表使用的是
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内部的专家。它们可能作为单独的查询执行,但相关数据可能会保存在内存中,直到所有查询完成。