我有一个非常简单的查询,我试图优化,它需要2~5秒才能执行。
这是我的CREATE TABLE
CREATE TABLE `artist` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) character set utf8 NOT NULL,
`bio` MEDIUMTEXT character set utf8 DEFAULT NULL,
`hits` INTEGER NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `album` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`artist_id` INTEGER NOT NULL,
`title` VARCHAR(100) character set utf8 NOT NULL,
`year` INTEGER,
`hits` INTEGER NOT NULL,
PRIMARY KEY (`id`),
KEY (`artist_id`)
);
CREATE TABLE `track` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) character set utf8 NOT NULL,
`lyric` MEDIUMTEXT character set utf8,
`album_id` INTEGER NOT NULL,
`hits` INTEGER NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY (`album_id`)
);
ALTER TABLE `album` ADD FOREIGN KEY (artist_id) REFERENCES `artist` (`id`);
ALTER TABLE `track` ADD FOREIGN KEY (album_id) REFERENCES `album` (`id`);
这是我正在运行的查询
SELECT DISTINCT artist.name, track.name
FROM track
LEFT JOIN album ON track.album_id = album.id
LEFT JOIN artist ON album.artist_id = artist.id
ORDER BY track.hits DESC
LIMIT 5
解释选择显示:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE track ALL NULL NULL NULL NULL 103796 Using temporary; Using filesort
1 SIMPLE album eq_ref PRIMARY PRIMARY 4 lyrics.track.album_id 1
1 SIMPLE artist eq_ref PRIMARY PRIMARY 4 lyrics.album.artist_id 1
我是MySQL的新手,但我想使用Using temporary;使用filesort是不好的,这就是为什么查询非常慢,你们可以在这里提示我吗?谢谢!
更新:这里的主要问题是,在具有不同ID的数据库中,同一首歌可以是5次,因为同一首歌可以在不同的专辑中。如果我不使用不同的,这不会发生,因为这个原因我必须
答案 0 :(得分:1)
您可以通过添加
来使用索引create index idx_tracks_on_album_id_name_hits on track(album_id, name, hits);
由于您在两个表中执行DISTINCT,因此没有索引可能找到唯一的行,因此它将它放入临时表中以删除重复项。
答案 1 :(得分:0)
我认为如果你在track
。hits
上创建索引,你可能会摆脱“使用临时;使用filesort”,其原因可能是因为MySQL无法找到要执行的索引那种。
ALTER TABLE `track`
ADD KEY `idx_hits` (`hits`);
让我知道它是否有效。
答案 2 :(得分:0)
为什么要使用DISTINCT?为什么使用LEFT JOIN(而不是JOIN)?
答案 3 :(得分:0)
此答案不是原始问题的100%答案。最初的问题是使用我的问题中的消息进行搜索时会出现什么情况,因此,以防万一它对其他人有帮助,我将为密切相关的问题保留解决方案。
“正在使用临时文件;正在使用文件排序” 实际上是一个红色鲱鱼,添加的索引从未被使用过。未使用索引,因为其中一个联接表的字符编码与另一个不同。
转换查询中的所有表,以便它们都使用相同的字符编码立即对其进行修复。
(在我们的示例中,将utf8编码的表转换为latin1编码)
希望它可以帮助某人。