添加带有 LIMIT 的 ORDER BY 时,简单 MySQL 查询被阻塞

Simple MySQL query is blocking when adding ORDER BY with LIMIT

我有一个tabletb_profilecomments:

4,3 GiB -- 总共 800 万行 -- InnoDB

有 3 个索引:

我运行的查询很简单:

SELECT *
FROM tb_profilecomments
WHERE profilecomment_user_id=6430
ORDER BY profilecomment_id DESC

在不到 1 秒的时间内得到结果(16.000 多行)。 当我现在将 LIMIT 1, 5 添加到查询中时,我必须等待 2 分钟以上才能获得结果。

不知道 mysql 后台发生了什么,为什么它会如此严重地减慢查询速度。

当我从查询中删除 ORDER BYLIMIT 时,一切正常。

按非索引 profilecomment_date 列排序时,速度较慢(7 秒),但不像使用索引主键 profilecomment_id 排序和限制时那样需要 2 分钟。

你知道哪里出了问题吗?可能是坏索引?如何查明?怎么修? ANALYZE TABLE 表示消息 "ok".

解释 tb_profilecomments:

显示创建 TABLE tb_profilecomments:

结果EXPLAIN SELECT * FROM tb_profilecomments WHERE profilecomment_user_id=6430 ORDER BY profilecomment_id DESC LIMIT 1, 5:

按降序在列 profilecomment_id 上创建索引。

语法格式:

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
    [index_type]

index_col_name:
    col_name [(length)] [ASC | DESC]

index_type:
    USING {BTREE | HASH}

示例:

create table t1(id int(9),name varchar(20),
               [UNIQUE] KEY (id DESC));

DESC 顺序不适用于主键。但它适用于 UNIQUE or normal index。您可以验证以下 link: http://sqlfiddle.com/#!9/ddf95/1& http://sqlfiddle.com/#!9/5c50d/1

旧版本忽略 DESC 并保持顺序 ASC。 详情请参考下方url:

http://dev.mysql.com/doc/refman/5.5/en/create-index.html

索引中的行是非常明确地排序的。 ASC 而已。即使是 5.7 手册页也说

An index_col_name specification can end with ASC or DESC. These keywords are permitted for future extensions for specifying ascending or descending index value storage. Currently, they are parsed but ignored; index values are always stored in ascending order.

MySQL 一直都有这个限制。 (升级无济于事。)

但是...这不会阻止代码按 DESC 顺序交付结果。

也就是说,MySQL 没有 DESC 索引的不足并不重要。这是一个重要的案例:ORDER BY x ASC, y DESC。无法构建 INDEX(在 MySQL 中)来有效处理该问题。

您的查询的最佳索引是

INDEX(user_id, comment_id);

user_id 将用于 WHERE user_id = _constant_,然后 comment_id 将以相反的顺序扫描以获得您想要的行。有或没有 LIMIT.

但是......索引必须处理全部 of WHERE, GROUP BY, and ORDER BYLIMIT 之前短路执行。 (否则,在LIMIT之前可以应用filesort,tmp table等。)

对于超慢查询,请提供 EXPLAIN SELECT ... 和(如果可能)EXPLAIN FORMAT=JSON SELECT ....

不要PRIMARY KEY 放到 InnoDB table 上!这是非常需要的。 (好吧,如果你要替换它就放弃它。)