Domanda

Below is my EXPLAIN query and the output. I'm very much a beginner (please forgive my SQL syntax...unless that's my problem!) - can anyone explain the order of the tables here please? I've played around with the order (in the query itself) and yet the TABLE artists is always top in the EXPLAIN output? I gather the order relates to when the tables are accessed - if so, why artists first?

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;
È stato utile?

Soluzione 2

Here is the fiddle for you: http://sqlfiddle.com/#!2/a6224/2/0

As @Daniel already said, MySQL takes into account not only indices, but also the number of rows in each table. The number of rows is low both in my fiddle and in your database - so it is hard to blame MySQL.

Note that even though STRAIGHT_JOIN will make the order of joins seem logical to you, it will not however make the execution plan prettier (I mean Using temporary; Using filesort red flags)

Altri suggerimenti

The order of joining your tables is depending on the SQL optimizer. The optimizer internally modifies your query to deliver results in a fast and efficient way (read this page for more details). To avoid internal join optimization you can use SELECT STRAIGHT_JOIN.

In your special case, the order is depending on the number of rows in each table and the availability of indexes. Have a look at these slides starting with page 25 for a little example.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top