【发布时间】:2014-12-21 01:03:25
【问题描述】:
我想了解 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, name created_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 (ie. (status, name, created_on, id, accessed_on))
它似乎正在应用 where 并且它会发现它需要并索引状态、名称、created_on 然后它会使用 INNER JOIN 并且它将使用 id 索引,然后是前 3 个。最后,它将查找accessed_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
【问题讨论】:
-
您可以使用
EXPLAIN SELECT * FROM A ...查看哪些键是正确的等等。