REGEXP的Mysql优化

时间:2012-09-07 12:26:31

标签: mysql regex optimization indexing query-optimization

此查询(使用不同的名称而不是“jack”)在我的慢查询日志中多次出现。为什么呢?

Users表有很多字段(超过我选择的这三个字段)和大约40.000行。

select name,username,id from Users where ( name REGEXP '[[:<:]]jack[[:>:]]' ) or ( username REGEXP '[[:<:]]jack[[:>:]]' ) order by name limit 0,5;

id是主要的和自动增量 name有一个索引 username有一个唯一的索引。

有时需要3秒钟! 如果我解释MySQL上的选择我得到了这个:

select type: SIMPLE
table: Users
type: index
possible keys: NULL
key: name
key len: 452
ref: NULL
rows: 5
extra: Using where

这是我能做的最好的吗?我能解决什么?

3 个答案:

答案 0 :(得分:14)

如果你必须使用regexp风格的WHERE子句,你肯定会受到慢查询问题的困扰。要使regexp样式的搜索起作用,MySQL必须将名称列中的每个值与regexp进行比较。而且,通过查看用户名列,您的查询也增加了麻烦。

这意味着MySQL无法利用任何索引,这就是所有DBMS加速查询大型表的方式。

您可以尝试一些方法。所有这些都涉及向REGEXP道别。

一个是这个:

WHERE name LIKE CONCAT('jack', '%') OR username LIKE CONCAT('jack', '%')

如果您在名称和用户名列上创建索引,这应该会非常快。它将查找以“jack”开头的所有名称/用户名。注意

WHERE name LIKE CONCAT('%','jack') /* SLOW!!! */

会查找以'jack'结尾的名称,但会像你的正则表达式搜索一样慢。

您可以做的另一件事是找出您的应用程序需要能够搜索部分名称或用户名的原因。您可以从应用程序中删除此功能,或者找出一些更好的方法来处理它。

可能更好的方法:

  1. 要求您的用户将他们的名字分解为给定姓名和姓氏字段,然后单独搜索。
  2. 创建一个单独的“搜索所有用户”功能,仅在用户需要时才使用,从而减少慢速正则表达式查询的频率。
  3. 使用某种预处理程序将自己的名字分解为单独的名称 - 单词表。在没有正则表达式的情况下搜索名称 - 单词表。
  4. 了解如何使用MySQL全文搜索此功能。
  5. 所有这些都涉及一些编程工作。

答案 1 :(得分:2)

我通过在where子句中添加fieldname!=''来达到50%的加速。它使mysql使用索引。

SELECT name, username, id 
FROM users 
WHERE name != '' 
    AND (name REGEXP '[[:<:]]jack[[:>:]]' or username REGEXP '[[:<:]]jack[[:>:]]') 
ORDER BY name 
LIMIT 0,5;

不是一个完美的解决方案,但有帮助。

答案 2 :(得分:-3)

在前面添加“LIKE”

SELECT cat_ID, categoryName FROM category WHERE cat_ID REGEXP '^15-64-8$' ORDER BY categoryName

SELECT cat_ID, categoryName FROM category WHERE cat_ID LIKE '15-64-8%' and cat_ID REGEXP '^15-64-8$' ORDER BY categoryName

总之,只有当你搜索短语时,才知道你知道的是什么,否则全文索引就是解决方案。