10

这个查询(用不同的名字而不是“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

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

4

3 回答 3

22

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

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

您可以尝试几件事。所有这些都涉及与 REGEXP 说再见。

一个是这样的:

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

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

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

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

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

可能的更好方法:

  1. 要求您的用户将他们的姓名分解为名字和姓氏字段,并分别搜索。
  2. 创建一个单独的“搜索所有用户”功能,该功能仅在用户需要时使用,从而降低慢速 regexp 样式查询的频率。
  3. 使用某种预处理程序自己将他们的名字分解成一个单独的名字词表。搜索不带正则表达式的名称词表。
  4. 弄清楚如何使用 MySQL 全文搜索来实现此功能。

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

于 2012-09-07T13:28:48.003 回答
2

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

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

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

于 2014-09-04T23:13:03.107 回答
-4

在前面加上“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

对于 cos,只有当 U r 搜索短语 U 知道以什么开头时才有效,否则全文索引是解决方案。

于 2013-02-07T18:42:13.197 回答