具有多个连接,group_concat和百万行的查询执行缓慢

时间:2016-02-03 06:32:46

标签: mysql cakephp cakephp-2.0 query-optimization

查询 -

    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将查询拆分为多个查询并按顺序执行。

EXPLAIN SELECT

1 个答案:

答案 0 :(得分:0)

没有。它需要扫描2M行,在其他表中查找数百万行,创建一个数百万行的tmp表,执行GROUP BY(可能没有filesort)并最终挖出2M行结果到客户。

好吧,也许......您使用的是哪种引擎?如果您使用InnoDB,innodb_buffer_pool_size的价值是多少?你有多少RAM?该设置应该是可用 RAM的70%左右。在冷缓存上运行查询时,这不会有帮助,因为会有很多I / O要做。但是,如果您再次运行查询,它可能会以10倍的速度运行。

请提供EXPLAIN SELECT ...,以便我们验证索引是否按预期使用。

降低您的期望 - 200万行值得花些时间。你要用那么多输出做什么?你需要不止一次吗?

<强>附加物

部分加速是为了许多表(samatm)提供更好的索引。特别是,复合查询会更快。 more details