查询 -
SELECT s.id,
GROUP_CONCAT(s.song_title SEPARATOR ', ') AS titles,
GROUP_CONCAT(a.artist_name SEPARATOR ', ') AS artists,
GROUP_CONCAT(al.album_title SEPARATOR ', ') AS albums,
GROUP_CONCAT(s.release_date SEPARATOR ', ') AS release_dates,
GROUP_CONCAT(sam.role SEPARATOR ', ') AS roles
FROM songs s
INNER JOIN song_artist_mappings sam ON sam.song_id = s.id
INNER JOIN artists a ON sam.artist_id = a.id
INNER JOIN album_track_mappings atm ON atm.song_id = s.id
INNER JOIN albums al on al.id = atm.album_id
GROUP BY s.id
指数 -
songs - id
song_artist_mappings - song_id, artist_id
album_track_mappings - song_id, album_id
albums - id
artists - id
查询返回~2百万行(这是歌曲表的大小)并且需要很多分钟才能执行。有什么方法可以优化吗?
编辑 - 一首歌曲(独特的歌曲ID)可以属于多个专辑以及艺术家。我必须以逗号分隔的字符串显示所有这些。如果不同行中的歌曲ID具有不同的标题,则会损坏少量数据。选择任何这些标题都没关系,所以我猜没有必要在song_title上使用GROUP_CONCAT。但是,我将不得不SELECT一个未在GROUP BY中列出的非聚合变量。由于数据损坏,我无法对song_title进行分组。
即使我将LIMIT 5附加到查询中,在30GB RAM计算机上InnoDB上的查询也需要很长时间。由于query_cache_size为0
,因此不会缓存任何查询编辑2 - 当我通过CakePHP关联获得相同的数据时,查询运行得快得多。 CakePHP将查询拆分为多个查询并按顺序执行。
答案 0 :(得分:0)
没有。它需要扫描2M行,在其他表中查找数百万行,创建一个数百万行的tmp表,执行GROUP BY
(可能没有filesort
)并最终挖出2M行结果到客户。
好吧,也许......您使用的是哪种引擎?如果您使用InnoDB,innodb_buffer_pool_size
的价值是多少?你有多少RAM?该设置应该是可用 RAM的70%左右。在冷缓存上运行查询时,这不会有帮助,因为会有很多I / O要做。但是,如果您再次运行查询,它可能会以10倍的速度运行。
请提供EXPLAIN SELECT ...
,以便我们验证索引是否按预期使用。
降低您的期望 - 200万行值得花些时间。你要用那么多输出做什么?你需要不止一次吗?
<强>附加物强>
部分加速是为了许多表(sam
和atm
)提供更好的索引。特别是,复合查询会更快。 more details