MySQL流水线订单似乎不起作用

时间:2016-03-08 05:13:47

标签: mysql sql performance database-performance

我有桌子 用户[id,name,status],索引为[status,name,id]

SELECT *
FROM user
WHERE status = 'active'
ORDER BY name, id
LIMIT 50

我有大约50000名状态为=='有效'的用户

1。)为什么MySQL解释在ROWS列中显示约50000?为什么它遵循所有叶节点,即使索引列等于order by子句?

2。)当我将order by子句改为

ORDER BY status, name, id

解释条款的EXTRA栏显示:

使用索引条件;用在哪里;使用filesort

是否有任何理由不能在此查询中使用索引顺序?

EDIT1:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `status` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `status_name_id` (`status`,`name`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

查询:

SELECT *
FROM `user`
WHERE status = 'complete'
ORDER BY status, name, id
LIMIT 50

解释:

id: 1
select_type: SIMPLE
table: f_order
type: ref
possible_keys: status_name_id
key: status_name_id
key_len: 768
ref: const
rows: 50331
Extra: "Using where; Using index; Using filesort"

最奇怪的是,如果我将SELECT语句更改为

SELECT *, count(id)

它再次使用索引,查询速度提高了两倍。额外的部分仅包含

Using where; Using index

表包含10万行,5种不同的状态和12个不同的名称。

MySQL:5.6.27

EDIT2:

另一个例子:

这需要400毫秒(平均)并进行显式排序

SELECT *
FROM `user`
WHERE status IN('complete')
ORDER BY status, name, id
LIMIT 50

这需要2ms(平均)并且没有明确排序

SELECT *
FROM `user`
WHERE status IN('complete', 'something else')
ORDER BY status, name, id
LIMIT 50

2 个答案:

答案 0 :(得分:1)

Q1:EXPLAIN有点蹩脚。在提供LIMIT估算时,它未考虑Rows的存在。请放心,如果它可以停止,它会。

Q2:它是否说它正在使用你的索引?请提供完整的EXPLAINSHOW CREATE TABLE

更多

使用INDEX(status, name, id),可以在索引中处理WHEREORDER BY LIMIT。因此它必须只读50行。

如果没有该索引(或者对查询几乎没有任何更改),需要读取大部分或全部表,存储在tmp表中,进行排序,然后才能剥离50行。

所以,我建议它比“显式排序可以杀死我的数据库服务器”更复杂。

答案 1 :(得分:0)

根据评论,这可能是错误。