下面是我的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;
答案 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
红旗)