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

标签 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

该查询返回大约 200 万行(这是歌曲表的大小),并且需要花费很多分钟来执行。有什么办法可以优化吗?

编辑 - 一首歌曲(唯一的歌曲 ID)可以属于多个专辑和艺术家。我必须将所有这些显示为逗号分隔的字符串。少量数据被损坏,其中不同行中的歌曲 ID 具有不同的标题。选择这些标题中的任何一个都可以,所以我想 Song_title 上的 GROUP_CONCAT 是没有必要的。但随后我将不得不选择一个未在 GROUP BY 中列出的非聚合变量。由于数据损坏,我无法对 Song_title 进行分组。

即使我将 LIMIT 5 附加到查询中,在 30GB RAM 计算机上的 InnoDB 上查询也会花费很多分钟。由于 query_cache_size 为 0,因此没有缓存任何查询

编辑 2 - 当我通过 CakePHP 关联获取相同的数据时,查询运行得更快。 CakePHP 将查询拆分为多个查询并按顺序执行它们。

EXPLAIN SELECT

最佳答案

没有。它需要扫描 2M 行,在其他表中查找几百万行,创建一个数百万行的临时表,执行 GROUP BY(可能没有文件排序)最后将 2M 结果行铲到客户端。

好吧,也许...您使用的是哪个引擎?如果您使用 InnoDB,innodb_buffer_pool_size 的值是多少?你有多少内存?该设置应约为可用 RAM 的 70%。当在冷缓存上运行查询时,这没有帮助,因为需要执行大量 I/O。但如果您第二次运行该查询,它的运行速度可能会快 10 倍。

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

降低您的期望 - 200 万行值得花费一些时间。这么多输出到底要做什么?您是否多次需要它?

附录

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

关于mysql - 具有多个连接、group_concat 和百万行的查询执行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35170061/

相关文章:

mysql - SQL 超出第 1 行 'CGPA' 列的值

MySQL转义空/空记录

json - 无法正确读取处理 Ajax 调用的 Cake PHP Controller 函数发送的 json 编码的成功/失败状态

php - CakePHP 中的 MySQL 表字段注释而不是名称

MySQL 选择 parent 和祖 parent

php - mysql查询最新日期

php - 服务器上的 CakeEmail 问题

CakePHP 2.0.x : ACL: Multiple Groups?

Cakephp:添加新附件而不添加新项目

mysql - 结果中的动态列名称