2016-09-08 45 views
0

我目前在一个MySQL用户表名和姓字段,以及一个搜索框,在这里他们可以输入两个,所以我的查询基本上是最快的方式MySQL的

SELECT name,surname FROM user 
WHERE CONCAT(name,' ',surname) LIKE '@search%' 

这工作得很好,但是在大型表格上变得非常慢,即使名称和姓氏列都被编入索引,并且当搜索被分解时,它很快,是否有一种方法来为连接字段建立索引或者当两个字段都编入索引时它们已经被编入索引,切换到全文索引会更快吗?

+1

使用concat将防止MySQL使用索引,因为它是派生值。长时间使用或是你最好的选择。 '姓名LIKE'@ search%'或姓氏LIKE'@ search%'''。 –

+0

如果您不介意以更多空间和维护后勤为代价获得速度,则可以添加连接列的索引列并搜索该列。 – Amnon

回答

0

我正确的是假设@search被替换的东西?

如果您正在搜索“文字”,那么FULLTEXT工程显着更快。但是,请注意它的局限性(停用词,最小词长度等)。

该特定尝试CONCAT(name,' ',surname) LIKE '@search%'只会检查'@search'的name的开头;我怀疑这是不是你想要的。你想要什么?

请记住name LIKE '@search%'name LIKE '%search%'要快很多,因为它可以使用INDEX(name),我认为你有吗?

如果你有两个INDEX(name)INDEX(surname),然后将是相当快的:

SELECT ... 
    WHERE name LIKE '@search%' 
UNION DISTINCT 
SELECT ... 
    WHERE surname LIKE '@search%'; 

这是因为这两个指标都可以使用。否则,他们不太可能都可以使用;相反,会有一个“表扫描”。 (使用OR如果你有一个老版本的MySQL,将不会如此。)

但是,如果用户用'%'或'_'启动@search,它将会很慢,因为前导通配符会导致表扫描。

同时,如果你不检查各种特殊字符,你是很受SQL注入

澄清

由于用户后更容易分开输入名称,你可以测试:

WHERE name LIKE '@name%' 
    AND surname LIKE '@surname%' 

然后让这两个(万一用户缩短任一):

INDEX(name, surname) 
INDEX(surname, name) 

那些比你拥有什么,更好。

由于数据输入似乎是单个字段,因此请使用客户端编程语言将其分为@name和@surname。 (在SQL中可能但很杂乱;请参阅SUBSTRING_INDEX()。)

阅读“组合索引”以了解为什么这些索引更好,以及为什么原始CONCAT特别低效。

+0

是@search被搜索所取代,我需要的是如果名字和姓氏是以空格作为搜索文本(即'Rick James')分开输入的,那么名字Rick和姓氏James的用户应该被返回。我可以做WHERE name LIKE'@ search%'和姓氏LIKE'%@ search%',但这会破坏姓氏上的索引并给我相同的问题,我可以使用全文作为姓,但限制可能是如果只输入姓氏的一个或两个字符,即'Rick Ja' – JacoT

0

编辑:这假定您的搜索开始包括名字,直到完成继续后面的名字。

只要你的搜索没有一个通配符你可以随时指数双双你的名字和姓字段作为一个指数显示为多列索引MySQL手册参考离开这里:http://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html

那我们强制查询使用多列索引。步骤如下:

1)创建索引

CREATE INDEX fullname ON table_name (name, surname) 

2)使用指数暗示告诉MySQL使用的多列索引查询

SELECT name,surname FROM user USE INDEX (fullname) WHERE CONCAT(name,' ',surname) LIKE '@search%' 

当只要没有通配符'%'在你的搜索开始,LIKE比较就会使用从左到右的索引。

最好的选择的确是将您的字段更改为FULLTEXT并利用MYSQL的新FULLTEXT搜索功能。下面是MySQL网站上的一个很好的例子,展示了这种搜索的实现方式:http://dev.mysql.com/doc/refman/5.7/en/fulltext-query-expansion.html