2012-03-29 98 views
0

SQL:对用户MySQL的LIKE查询时间太长

 SELECT 
      COUNT(usr.id) as `total_results` 
     FROM 
      users as usr 
      LEFT JOIN profile as prof 
       ON prof.uid = usr.uid 
     WHERE 
      usr.username LIKE '%a%' 
      OR 
      prof.name LIKE '%a%' 

指标:在个人

index1 - uid 
index2 - uid,name 
index3 - name 

uid - uid 
username - username 

指标说明:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 PRIMARY  usr  ALL  NULL NULL NULL NULL 18387 
1 PRIMARY  prof ref  index2,index1 index2 8 site.usr.uid 1 Using where 
2 DEPENDENT SUBQUERY sub  ref  i3,index1,index2 i3 16 site.usr.uid,const 1 Using index 

以上查询大约需要0.1221

我该如何让它运行得更快?

+1

删除你的'LIKE'上的开始'%' – Lamak 2012-03-29 15:54:00

+1

你想达到什么目的?您是否真的想要统计所有名称或用户名中带有字母“a”的条目? – liquorvicar 2012-03-29 15:58:24

+0

@liquorvicar是的,我正在尝试获取搜索记录的数量 – fxuser 2012-03-29 16:00:23

回答

0

我删除了这个查询,以便它不会显示总结果计数当一个搜索完成。

似乎是一个临时解决方案,甚至是永久性的。

3

LIKE子句中的初始%意味着这些列的索引不能使用。我相信MySQL full text index可能会做你想做的。

0

它尽可能多地使用索引(两个主键都用于左连接)。主要的问题是LIKE'%a%',因为在这种情况下它不能使用索引(如果它是'%',它将能够在用户名和名称上使用索引)。你可以尝试什么(不知道这是否会加快速度)是使用concat(usr.username,prof.name),如'%a%',但你可能不会注意到任何区别。

全文索引不起作用,因为全文索引在搜索整个单词时非常有用。

无论如何,对于查询你有你的名字和用户名索引是无用的,只是占用空间,所以我会删除它们。如果LIKE'a%'满足您的需求,那么这些索引就有意义。

如果'a%'不能满足您的需求,您可以查看其他选项,例如mysql查询缓存(如果您希望频繁重复查询)。

+0

所以我做这个方法,我用来搜索或没有什么可以加速的东西?不能相信没有任何方法... – fxuser 2012-03-29 16:01:28

+0

据我所知,没有办法写它工作得更快,并保持相同的语义。 – 2012-03-29 16:07:57

6

要匹配的字符串的开始处的%使得索引无法使用。开头的通配符使索引无效,并且MySQL必须在每个行的该列内进行搜索。它不能跳下去。如果您知道您正在搜索的项目将位于字段开头的开头,则可以删除开始的'%'。但是,如果您正在寻找'steve',我的回答将会返回'steve','steven','steve-boss',而不是'boss-steve'或'realsteve'。

+0

所以其他网站如何使用搜索?有没有更好的方法可以使用? – fxuser 2012-03-29 16:02:26

+0

@fxuser - 其他网站不只是搜索单个字符。像谷歌这样的大型网站不会使用任何特定于这种搜索的关系数据库。为此,最好使用全文索引,但如果您希望搜索包含字符'a'的所有用户,那么它的作用不同于仅搜索单个字符 – Lamak 2012-03-29 16:06:47

+0

@fxuser,然后在MySQL中没有更快的方式。你将不得不升级你的硬件或重新设计你的数据库。老实说,18k的记录似乎并不像查询那么慢。 – 2012-03-29 18:20:19

0

1)购买更快的数据库服务器。

2)重新设计你的数据库,这样你就不必在两个地方的用户名看或只允许用户搜索的一个或另一个