嵌套的“选择...”表现很慢 - 如何解决?

时间:2011-12-07 21:33:02

标签: mysql sql

这里我有一个简单的连接查询。如果前两个查询得到结果,则整个查询可以在0.3秒内完成,但如果前两个选择不能获取任何结果,则整个查询将花费超过半分钟。是什么导致这种差异?如何解决这个问题并提高性能?

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

这是表结构:

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;

1 个答案:

答案 0 :(得分:2)

该查询中没有联接;有两个子选择。

加入的查询将是:

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;

应用于每个的EXPLAIN将显示联接比子选择更好的原因:子选择将扫描整个music表(主查询),而优化器可以选择表的顺序来扫描连接,允许MySQL使用索引来获取所有表中所需的行。