我目前在mysql用户表中有一个名字和姓氏字段,以及一个可以输入两者的搜索框,所以我的查询基本上是
SELECT name,surname FROM user
WHERE CONCAT(name,' ',surname) LIKE '@search%'
这样可以正常工作,但是在大型表上变得非常慢,即使名称和姓氏列都被编入索引,并且当搜索被分解时它很快,是否有一种方法可以索引连接字段或者它们已经编入索引当两个字段都被编入索引时,切换到全文索引会更快吗?
答案 0 :(得分:1)
我是否正确假设@search
被某些东西取代?
如果您要搜索“字词”,那么FULLTEXT
可以更快地 。但是,要注意它的局限性(停用词,最小字长等)。
该特定尝试CONCAT(name,' ',surname) LIKE '@search%'
只会检查name
的开头是否为'@search';我怀疑这是不是你想要的。你想要什么?
请注意,name LIKE '@search%'
比name LIKE '%search%'
要快得多,因为它可以使用INDEX(name)
,我认为你有这个?{/ p>
如果您同时拥有INDEX(name)
和INDEX(surname)
,那么此会相当快:
SELECT ...
WHERE name LIKE '@search%'
UNION DISTINCT
SELECT ...
WHERE surname LIKE '@search%';
这是因为可以使用这两个索引。否则,它们不太可能都被使用;而是会有一个“表扫描”。 (如果你有一个旧版本的MySQL,OR
的使用也不会那么好。)
但是,如果用户使用'%'或'_'启动@search
,则它将是sloooow,因为前导通配符将导致表扫描。
同时,如果您不检查各种特殊字符,那么非常容易受到SQL注入!
澄清后
由于用户单独输入名称,因此您可以更轻松地进行测试:
WHERE name LIKE '@name%'
AND surname LIKE '@surname%'
然后同时拥有这两个(如果用户缩短其中任何一个):
INDEX(name, surname)
INDEX(surname, name)
。
由于数据输入似乎是单个字段,因此请使用客户端编程语言将其拆分为@name和@surname。 (在SQL中有可能,但很麻烦;请参阅INDEX(name), INDEX(surname)
。)
阅读“复合索引”以了解为什么这些索引更好,以及为什么原始SUBSTRING_INDEX()
效率特别低。
答案 1 :(得分:1)
编辑:这假设您的搜索开始包括第一个名称,直到完成后继续使用姓氏。
只要您的搜索在左侧没有通配符,您就可以始终将您的姓名和姓氏字段索引为一个索引,如多列索引的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