添加带有 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 BY
或 LIMIT
时,一切正常。
按非索引 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:
索引中的行是非常明确地排序的。 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 BY
在 LIMIT
之前短路执行。 (否则,在LIMIT
之前可以应用filesort,tmp table等。)
对于超慢查询,请提供 EXPLAIN SELECT ...
和(如果可能)EXPLAIN FORMAT=JSON SELECT ...
.
不要 将 PRIMARY KEY
放到 InnoDB table 上!这是非常需要的。 (好吧,如果你要替换它就放弃它。)
我有一个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 BY
或 LIMIT
时,一切正常。
按非索引 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:
索引中的行是非常明确地排序的。 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 BY
在 LIMIT
之前短路执行。 (否则,在LIMIT
之前可以应用filesort,tmp table等。)
对于超慢查询,请提供 EXPLAIN SELECT ...
和(如果可能)EXPLAIN FORMAT=JSON SELECT ...
.
不要 将 PRIMARY KEY
放到 InnoDB table 上!这是非常需要的。 (好吧,如果你要替换它就放弃它。)