Reputation: 3401
Here I have a simple join query. If first two queries get results, the whole query can be done in 0.3 secs, but if the first 2 select doesn't fetch any result, the whole query will cost more than half a minute. What causes this difference? How to fix this problem and improve the performance?
SELECT * FROM music WHERE id IN
(
SELECT id FROM music_tag_map WHERE tag_id IN
(
SELECT id FROM tag WHERE content ='xxx'
)
)
LIMIT 10
Here's the table structure:
CREATE TABLE `tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index2` (`content`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `music` (
`id` int(7) NOT NULL AUTO_INCREMENT,
`name` varchar(500) NOT NULL,
`othername` varchar(200) DEFAULT NULL,
`player` varchar(3000) DEFAULT NULL,
`genre` varchar(100) DEFAULT NULL,
`sounds` text,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `player` (`player`(255)),
KEY `name` (`othername`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `music_tag_map` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`music_id` int(7) NOT NULL,
`tag_id` int(7) NOT NULL,
`times` int(11) DEFAULT '1',
PRIMARY KEY (`id`),
KEY `music_id` (`music_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `music_tag_map_ibfk_1` FOREIGN KEY (`id`) REFERENCES `music` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `music_tag_map_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Upvotes: 1
Views: 2195
Reputation: 77450
There are no joins in that query; there are two sub-selects.
A joined query would be:
SELECT *
FROM music
JOIN music_tag_map ON music.id=music_tag_map.id
JOIN tag ON music_tag_map.tag_id=tag.id
WHERE tag.content = ?
LIMIT 10;
An EXPLAIN
applied to each will show you why the join performs better than the sub-select: the sub-select will scan the entire music
table (the primary query), while the optimizer can pick the order of tables to scan for the joins, allowing MySQL to use indices to get only the needed rows from all the tables.
Upvotes: 2