在什么执行级别,MySQL会使用ORDER BY的索引?

时间:2014-12-21 01:03:25

标签: mysql sql

我想了解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执行遵循以下顺序。但我不确定订单选择和订单是如何运作的。

  1. FROM clause
  2. WHERE子句
  3. GROUP BY子句
  4. HAVING条款
  5. SELECT条款
  6. ORDER BY子句
  7. 问题

    使用id列启动索引会不会更好,或者在这种情况下无关紧要因为在{JOIN之前首先执行WHERE?或者它应该是

    第二个问题,access_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.最后,它会将visited_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
    

1 个答案:

答案 0 :(得分:1)

此查询的最佳索引是:A(status, name, created_on)B(id)。这些索引将满足where子句,并使用连接的索引B

此索引不会用于排序。使用任何索引进行排序有两个主要障碍。第一个是加入。第二个是created_on上的不平等。有些数据库可能会在A(status, name, accessed_on)上使用索引,但我认为MySQL不够聪明。

您不希望id作为索引中的第一列。这排除了使用索引对A进行过滤,因为id用于join而不是where