如何高效查询SQL数据库中的多对多关系?含场景优化疑问
关于SQLite歌曲与作曲家多对多关系的优化问题解答
问题1:能否用单条SQL一次性获取所有歌曲及其对应作曲家信息?
完全可以,通过JOIN关联查询就能避免逐行查询的N+1问题,有两种实用实现方式:
方式1:返回歌曲-作曲家对应行
这种方式会把一首歌曲的多个作曲家拆分成独立行返回,适合后续在代码中自行分组处理:
SELECT s.id AS song_id, s.title, c.id AS composer_id, c.name FROM songs s INNER JOIN songComposers sc ON s.id = sc.song_id INNER JOIN composers c ON sc.composer_id = c.id ORDER BY s.id;
如果需要包含暂无作曲家的歌曲,把INNER JOIN替换为LEFT JOIN即可。
方式2:合并同一歌曲的作曲家信息
用SQLite内置的GROUP_CONCAT函数,把同一歌曲的作曲家姓名合并为逗号分隔的字符串,每行对应一首完整歌曲:
SELECT s.id, s.title, GROUP_CONCAT(c.name, ', ') AS composers FROM songs s INNER JOIN songComposers sc ON s.id = sc.song_id INNER JOIN composers c ON sc.composer_id = c.id GROUP BY s.id, s.title ORDER BY s.id;
问题2:是否应在songs表中冗余作曲家信息以提升性能?
不推荐这么做,核心原因如下:
- 破坏数据一致性:作曲家改名时,需要遍历所有关联歌曲行更新冗余字段,稍有疏漏就会出现数据矛盾;若歌曲有多个作曲家,冗余字段需用特殊格式存储(如逗号分隔),后续修改、筛选作曲家会变得异常繁琐。
- 性能提升无必要:只要给
songComposers表的song_id和composer_id字段添加索引,JOIN查询的效率完全能覆盖绝大多数业务场景。 - 仅极端场景可考虑:只有当数据量超百万级、查询频率极高且无法通过索引优化时,才可以权衡一致性维护成本后尝试局部冗余,但这属于特殊优化,绝非常规方案。
内容的提问来源于stack exchange,提问作者Michele Spagnolo
相关产品推荐
相关产品推荐

