2011-12-07 50 views
1

這裏我有一個簡單的連接查詢。如果前兩個查詢得到結果,則整個查詢可以在0.3秒內完成,但是如果前2個選擇未獲取任何結果,則整個查詢將花費半分鐘以上。是什麼造成這種差異?如何解決這個問題並改善性能?嵌套的「select ... in」表現很慢 - 如何解決?

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; 
+2

「這裏我有一個簡單的連接查詢。」我不會考慮加入查詢。我看到隱式連接,但沒有連接操作符。如果你使用正確的連接,你可能會獲得更好的性能。你是否也在聲明中做了EXPLAIN? – Corbin

+0

如何以'INSERT'語句的形式回覆一些示例數據? – outis

回答

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使用索引從所有表中只獲取所需的行。