REGEXP的Mysql优化

Pon*_*ons 6 regex mysql indexing optimization 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
Run Code Online (Sandbox Code Playgroud)

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

O. *_*nes 15

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

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

你可以尝试一些事情.所有这些都涉及到REGEXP说再见.

一个是这样的:

WHERE name LIKE CONCAT('jack', '%') OR username LIKE CONCAT('jack', '%')
Run Code Online (Sandbox Code Playgroud)

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

WHERE name LIKE CONCAT('%','jack') /* SLOW!!! */
Run Code Online (Sandbox Code Playgroud)

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

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

可能更好的方法:

  1. 要求您的用户将其名称分解为给定名称和姓氏字段,并单独搜索.
  2. 创建单独的"搜索所有用户"功能,仅在用户需要时才使用,从而降低慢速正则表达式查询的频率.
  3. 使用某种预处理程序将自己的名称分解为单独的名称 - 单词表.在没有正则表达式的情况下搜索名称 - 单词表.
  4. 弄清楚如何使用MySQL全文搜索此功能.

所有这些都涉及一些编程工作.

  • 了解.正则表达式搜索是解决您问题的正确方法.但它本来就是*慢.对未锚定的文本列索引的任何搜索(即,不以列中的第一个字符位置开头)都会遇到同样的问题.所以,是的,`LIKE'%jack%'`像regexp式搜索一样慢.这是因为索引是按顺序组织的,并且可以按顺序快速随机访问.想想在电话簿中查找"琼斯".您可以轻松找到具有该名称的第一个人.但如果你用每个人物"一个"来查看,那就需要永远. (3认同)