针对 REGEXP 的 Mysql 优化

标签 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

这是我能做的最好的吗?我可以解决什么问题?

最佳答案

如果你必须使用正则表达式风格的 WHERE 子句,你肯定会被慢查询问题所困扰。为了使正则表达式搜索起作用,MySQL 必须将名称列中的每个值与正则表达式进行比较。而且,您的查询还查看了您的用户名列,从而使问题加倍。

这意味着 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 全文搜索来实现此功能。

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

关于针对 REGEXP 的 Mysql 优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12318083/

相关文章:

mysql - 将值从一个表传递到另一个表

PHP Mysql,如果用户提交空则指定默认值

asp.net - 重定向主页

c# - Regex 词边界表达式

java - 输入流上的正则表达式

Mysql:什么是碎片表,为什么要对它们运行 OPTIMIZE?

java - 当 exec (i/j) 和 (i % j) 时,jvm 会执行一还是两次计算?

c# - 使用 C# 在 TextBox 中准备语句查询

php - 如何使用 PHP 从 MYSQL 按日期排序

java - final 成员变量有利于更好的 GC 吗?