我想了解MySQL在使用ORDER BY时会在什么时间点使用索引列。
例如查询
SELECT * FROM A
INNER JOIN B ON B.id = A.id
WHERE A.status = 1 AND A.name = 'Mike' AND A.created_on BETWEEN '2014-10-01 00:00:00' AND NOW()
ORDER BY A.accessed_on DESC
据我所知,上述查询的一个好的索引是表 A (id, status, namecreated_on,accessed_on)
上的索引和 B.id
上的另一个索引.
我还了解到SQL执行遵循以下顺序。但我不确定订单选择和订单如何运作。
- FROM 子句
- WHERE 子句
- GROUP BY 子句
- HAVING 子句
- SELECT 子句
- ORDER BY 子句
问题
使用 id
列启动索引是否会更好,或者在这种情况下并不重要,因为 WHERE
在 JOIN 之前先执行?或者应该是
第二个问题accessed_on列应该位于索引组合的开头、末尾还是中间?或者 id
列应该位于 WHERE
子句中的所有列之后吗?
我很欣赏详细的答案,这样我就可以了解 MySQL/SQL 的执行级别
已更新
我向表 A 和表 B 添加了几百万条记录,然后添加了多个索引来查看哪个是最佳索引。但是,MySQL 似乎喜欢索引 id_2 (即(status、name、created_on、id、accessed_on))
它似乎正在应用 where ,它会发现它需要对状态、名称、created_on 进行索引,然后它会应用 INNER JOIN
并使用 id
index 后跟第一个 3。最后,它将查找 access_on 作为最后一列。因此索引(status, name,created_on,id,accessed_on)
符合相同的执行顺序
这是表结构
CREATE TABLE `a` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`status` int(2) NOT NULL,
`name` varchar(255) NOT NULL,
`created_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`accessed_on` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `status` (`status`,`name`),
KEY `status_2` (`status`,`name`,`created_on`),
KEY `status_3` (`status`,`name`,`created_on`,`accessed_on`),
KEY `status_4` (`status`,`name`,`accessed_on`),
KEY `id` (`id`,`status`,`name`,`created_on`,`accessed_on`),
KEY `id_2` (`status`,`name`,`created_on`,`id`,`accessed_on`)
) ENGINE=InnoDB AUTO_INCREMENT=3135750 DEFAULT CHARSET=utf8
CREATE TABLE `b` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3012644 DEFAULT CHARSET=utf8
最佳答案
此查询的最佳索引是:A(status, name,created_on)
和 B(id)
。这些索引将满足 where
子句,并使用索引连接到 B
。
该索引不会用于排序。使用任何索引进行排序有两个主要障碍。第一个是加入。第二个是 created_on
上的不相等。有些数据库可能会想出在 A(status, name,accessed_on)
上使用索引,但我认为 MySQL 不够智能。
您不希望 id
作为索引中的第一列。这会阻止使用索引对 A
进行过滤,因为 id
用于 join
而不是在 where
中.
关于mysql - MySQL 将在什么执行级别使用 ORDER BY 索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27585849/