针对标签上的多对多连接优化 MySQL 查询

Posted

技术标签:

【中文标题】针对标签上的多对多连接优化 MySQL 查询【英文标题】:Optimize MySQL query for Many-To-Many Join on tags 【发布时间】:2012-10-03 08:50:12 【问题描述】:

我需要选择链接到特定标签的所有文章,但我还想要与每篇文章关联的所有其他标签。凭借我有限的 SQL 知识,我进行了以下 mysql 查询,该查询有效,但似乎效率不高。

SELECT a.id, a.name, c.id AS topic_id, c.name AS topic, GROUP_CONCAT(t.id) AS tag_ids, GROUP_CONCAT(t.name) AS tags, a.description
FROM tag t 
LEFT JOIN artifacts_tags j ON t.id = j.tag_id
LEFT JOIN artifact a ON a.id = j.artifact_id
LEFT JOIN topic c ON c.id = a.topic_id

LEFT JOIN artifacts_tags aj ON a.id = aj.artifact_id
LEFT JOIN tag ts ON ts.id = aj.tag_id
WHERE ts.slug = 'summer'
AND a.is_public = 1 
GROUP BY a.id

如果有人能提出更有效的查询,我将不胜感激。

实际上,我还需要类似的标签(所有标签都属于带有 slug 'summer' 的标签所属的主题),但我有另一个查询。如果我可以使用相同的查询获得类似的标签会更好,但我不知道如何。表tagtopic 表具有多对一关系。

【问题讨论】:

您如何衡量效率?如果查询执行您想要的操作并在合理的时间内执行,并且您可以轻松理解和修改您的查询,那么它如何更有效?也就是说,在我看来,您可以将 LEFT 替换为 INNER 连接 - 但这取决于您的数据库内容和语义。 @AlexMonthy 你是对的。我应该使用 INNER 连接。谢谢 【参考方案1】:

非确定性分组: SQL 检索既不在聚合函数中也不在 GROUP BY 表达式中的列,因此这些值在结果中将是不确定的。

GROUP BY 在不同的表上: 这将强制使用临时表和文件排序,这可能是一个巨大的性能问题,并且会消耗大量内存和磁盘上的临时空间。

【讨论】:

在这种情况下,SELECT 列表中的所有列都由a.id(表article 的主键)确定,因此查询返回确定性结果。

以上是关于针对标签上的多对多连接优化 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

针对特定集合的多对多关系核心数据查询

Mysql连接查询匹配所有标签的多个“标签”(多对多关系)?

MySQL选择连接多对多表加上IN和NOT IN

mysql - 来自桥接表的多对多查询[关闭]

在 laravel 中搜索查询并计算结果的多对多关系

Django查询集获得精确的多对多查询[重复]