MySQL关联查询速度缓慢

7
<?php
$db = new mysqli(//editted out db credentials);

if($db->connect_errno > 0){
    die('Unable to connect to database [' . $db->connect_error . ']');
}
$sql = "SELECT m.ID, m.Title, GROUP_CONCAT(a.Title) AS Artist
FROM mp3s m
LEFT JOIN artist_relations ar ON ar.mp3ID = m.ID
LEFT JOIN artists a ON a.ID = ar.artistID
GROUP BY m.ID
ORDER BY ID
LIMIT 0,30;
";

if($result = $db->query($sql)){
echo "<table>";
while($row = $result->fetch_assoc()){
    echo "<tr>";  
    echo "<td>".$row['Title']."</td>";
    echo "<td>".$row['Artist']."</td>";
    echo "</tr>";  
}
echo "</table>";
}

?> 

这个查询是正确的,但速度非常慢。

这个数据库有3个字段:

`artists` : ID , Title
`mp3s` : ID , Title
`artist_relations` : mp3ID , artistID

i need this:

row1: titlemusic1 - artist1 , artist4 , artist5
row2: titlemusic2 - artist1
row3: titlemusic1 - artist3 , artist8
row4: titlemusic1 - artist9 , artist10
...

mp3s,艺术家和艺术家关系各有超过20000条记录

EXPLAIN SELECT m.ID, m.Title, .... :
    id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
    1   SIMPLE  m   ALL     NULL    NULL    NULL    NULL    23718   Using temporary; Using filesort
    1   SIMPLE  ar  ALL     NULL    NULL    NULL    NULL    24337   
    1   SIMPLE  a   eq_ref  PRIMARY     PRIMARY     4   ganools_rj.ar.artistID  1   

--

-- 表格artist_relations的结构

如果不存在,就创建表格artist_relations,包含以下列: artistID:int类型,长度为11,不能为空 mp3ID:int类型,长度为11,不能为空 使用InnoDB引擎,默认字符集为latin1。


--

-- 表格artists的结构

如果不存在,就创建表格artists,包含以下列: ID: int类型,长度为11,不能为空,自动递增 Title: varchar类型,长度为155,不能为空 主键为ID 使用InnoDB引擎,字符集为latin1,默认自动递增值为9005。


--

-- 表格mp3s的结构

如果不存在,就创建表格mp3s,包含以下列: ID: int类型,长度为11,不能为空,自动递增 Title: varchar类型,长度为155,不能为空 imageURL: varchar类型,长度为155,不能为空 mp3URL: varchar类型,长度为155,不能为空 Description: text类型 Lyric: text类型 album: varchar类型,长度为155,默认为空 plays: int类型,长度为11,默认为空 pubDate: date类型,不能为空 主键为ID 使用InnoDB引擎,字符集为latin1,默认自动递增值为22936。



哪些列有索引?您可以在查询前面加上EXPLAIN来运行查询,输出将为您提供正在发生的情况的想法。EXPLAIN SELECT m.ID, m.Title, .... - slapyo
基本的经验法则是:在决策上下文中使用的任何字段(例如where、join、order、case等)都应该有一个索引。 - Marc B
解释SELECT m.ID,m.Title,....: id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE m ALL NULL NULL NULL NULL 23718 使用临时表; 使用文件排序 1 SIMPLE ar ALL NULL NULL NULL NULL 24337
1 SIMPLE a eq_ref PRIMARY PRIMARY 4 ganools_rj.ar.artistID 1
- prog renalin
请为这些表中的每个表发布SHOW CREATE TABLE。如果您实际上已经定义了外键约束,则索引将被强制执行,并且性能将得到提高。 - Michael Berkowski
展示创建表插入 - prog renalin
1个回答

3
尝试为artist_relations.mp3ID、artist_relations.artistID和mp3s.ID创建索引。请参见CREATE INDEX

请解释得更详细一些 :( - prog renalin
如果您在JOIN、GROUP BY或ORDER BY中使用artist_relations.mp3ID、artist_relations.artistID和mp3s.ID属性,最好为这些属性创建索引。请注意,参见此讨论。 - user4266998
我的英文非常差,你能帮我写出可以运行的代码吗?:( - prog renalin
ALTER TABLE artist_relations ADD INDEX (mp3ID); ALTER TABLE artist_relations ADD INDEX (artistID); ALTER TABLE mp3s ADD INDEX (ID); 将artist_relations表格增加mp3ID索引; 将artist_relations表格增加artistID索引; 将mp3s表格增加ID索引; - user4266998

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接