使用LIMIT添加ORDER BY时,简单的MySQL查询会阻塞

时间:2015-08-29 11:11:17

标签: mysql sql-order-by query-optimization innodb sql-limit

我有一张表 tb_profilecomments

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

有3个索引:

Database SHOW INDEX

我运行的查询很简单:

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"。

EXPLAIN tb_profilecomments

EXPLAIN TABLE command

显示创建表 tb_profilecomments

SHOW CREATE TABLE command

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

EXPLAIN SELECT command

2 个答案:

答案 0 :(得分:1)

索引中的行非常有序。仅ASC。甚至5.7手册页也说

  

index_col_name规范可以以ASC或DESC结尾。这些关键字允许用于将来的扩展,以指定升序或降序索引值存储。目前,他们被解析但被忽略;索引值始终按升序存储。

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

但是......索引必须WHERE之前处理<{1}},GROUP BYORDER BY的所有短路执行。 (否则,在应用LIMIT之前,有一个filesort,tmp表等。)

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

EXPLAIN FORMAT=JSON SELECT ...放在InnoDB表上!这是非常需要的。 (好的,如果要更换它,请将其丢弃。)

答案 1 :(得分:0)

按列递减顺序在列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。您可以通过以下链接进行验证:  http://sqlfiddle.com/#!9/ddf95/1&amp;  http://sqlfiddle.com/#!9/5c50d/1

旧版本忽略DESC并保留订单ASC。 详情请参阅以下网址:

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