试图理解mySQL中查询的EXPLAIN结果

时间:2014-01-30 17:24:33

标签: mysql explain

下面是我的EXPLAIN查询和输出。我是一个非常初学者(请原谅我的SQL语法......除非那是我的问题!) - 有人能解释一下表格的顺序吗?我已经玩过订单(在查询本身中),而TABLE 艺术家总是在EXPLAIN输出中排名第一?我收集了关于何时访问表格的订单 - 如果是,为什么艺术家首先?

EXPLAIN
SELECT album_name, artist_name, genre_name
FROM albums
JOIN genres USING (genre_pk)
JOIN artists USING (artist_pk)
ORDER BY album_name;


| id | select_type | table   | type   | possible_keys      | key       | key_len | ref                     | rows | Extra                           |
+----+-------------+---------+--------+--------------------+-----------+---------+-------------------------+------+---------------------------------+
|  1 | SIMPLE      | artists | ALL    | PRIMARY            | NULL      | NULL    | NULL                    |    5 | Using temporary; Using filesort |
|  1 | SIMPLE      | albums  | ref    | genre_pk,artist_pk | artist_pk | 2       | music.artists.artist_pk |    1 | NULL                            |
|  1 | SIMPLE      | genres  | eq_ref | PRIMARY            | PRIMARY   | 1       | music.albums.genre_pk   |    1 | NULL                            |

SHOW CREATE TABLE info:

CREATE TABLE `artists` (
    `artist_pk` smallint(4) unsigned NOT NULL AUTO_INCREMENT,
    `artist_name` varchar(57) NOT NULL,
    `artist_origin` enum('UK','US','OTHER') DEFAULT NULL,
    PRIMARY KEY (`artist_pk`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

CREATE TABLE `genres` (
    `genre_pk` tinyint(2) unsigned NOT NULL AUTO_INCREMENT,
    `genre_name` varchar(30) NOT NULL,
    PRIMARY KEY (`genre_pk`),
    UNIQUE KEY `genre_name` (`genre_name`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;

CREATE TABLE `albums` (
    `album_pk` smallint(4) unsigned NOT NULL AUTO_INCREMENT,
    `genre_pk` tinyint(2) unsigned NOT NULL,
    `artist_pk` smallint(4) unsigned NOT NULL,
    `album_name` varchar(57) NOT NULL,
    `album_year` year(4) DEFAULT NULL,
    `album_track_qty` tinyint(2) unsigned NOT NULL,
    `album_disc_num` char(6) NOT NULL DEFAULT '1 of 1',
    PRIMARY KEY (`album_pk`),
    KEY `genre_pk` (`genre_pk`),
    KEY `artist_pk` (`artist_pk`),
    FULLTEXT KEY `album_name` (`album_name`),
    CONSTRAINT `albums_ibfk_1` FOREIGN KEY (`genre_pk`) REFERENCES `genres` (`genre_pk`),
    CONSTRAINT `albums_ibfk_2` FOREIGN KEY (`artist_pk`) REFERENCES `artists` (`artist_pk`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

2 个答案:

答案 0 :(得分:2)

加入表的顺序取决于SQL优化器。优化程序在内部修改您的查询,以快速有效的方式提供结果(read this page for more details)。要避免内部联接优化,您可以使用SELECT STRAIGHT_JOIN

在您的特殊情况下,订单取决于每个表中的行数和索引的可用性。从第25页开始,请查看these slides以获取一些示例。

答案 1 :(得分:0)

这是你的小提琴:http://sqlfiddle.com/#!2/a6224/2/0

正如@Daniel所说,MySQL不仅考虑了索引,还考虑了每个表中的行数。在我的小提琴和数据库中,行数都很少 - 所以很难责怪MySQL。

请注意,即使STRAIGHT_JOIN会使连接顺序看起来合乎逻辑,但它也不会使执行计划更漂亮(我的意思是Using temporary; Using filesort红旗)