mysql LIKE查询耗时太长

时间:2012-03-29 15:50:10

标签: mysql sql indexing

SQL:

        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%' 

用户索引:

uid - uid
username - username

个人资料中的索引

index1 - uid
index2 - uid,name
index3 - name

EXPLAIN:

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

如何让它跑得更快?

5 个答案:

答案 0 :(得分:8)

要匹配的字符串开头的%使得它无法使用索引。开头的通配符使索引无效,MySQL必须在每个行的该列中进行搜索。它不能跳过。如果您知道您要搜索的项目位于字段开头的开头,则可以删除开头'%'。

然而,如果你正在寻找'史蒂夫',我的回答将是'steve','steven','steve-boss',而不是'boss-steve'或'realsteve'。

答案 1 :(得分:3)

LIKE子句中的初始%表示无法使用这些列的索引。我相信MySQL full text index可以做你想做的事。

答案 2 :(得分:1)

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

2)重新设计您的数据库,这样您就不必在两个地方查找用户名或只允许用户搜索其中一个

答案 3 :(得分:0)

它尽可能多地使用索引(左侧连接的主键都是)。主要问题是LIKE'%a%',因为在这种情况下它不能使用索引(如果它是'a%',它将能够在用户名和名称上使用索引)。您可以尝试(不确定这是否会加速)是使用concat(usr.username,prof.name),如'%a%',但您可能不会注意到任何差异。

全文索引不起作用,因为当您搜索整个单词时,全文索引很有用。

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

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

答案 4 :(得分:0)

我删除了此查询,因此在搜索完成后它不会显示总结果数。

似乎是临时解决方案,甚至是永久解决方案。