如何更新多对多链接表中的数据?

时间:2017-10-06 10:32:54

标签: database relational-database

为了简单起见,我们假设有一个Post表和一个Tags表(不是实际的用例,但这样可以保持简单)

帖子表

id |  title
--------------------------------
1  |  Random Text Here
2  |  Another Post About Stuff

标签表

id | tag
--------------------------------
1  | javascript
2  | node
3  | unrelated-thing

posts_tags表

id| post_id | tag_id
--------------------------------
1 | 1       | 1
2 | 1       | 2
3 | 1       | 3
4 | 2       | 2

帖子可以包含许多标签,单个标签可以与许多帖子相关联。

Web应用程序假设让我们假装添加/删除标记不会在Web应用程序中针对链接表触发单个异步操作。  相反,用户将编辑帖子(添加或删除已创建的任何标签),然后点击保存。 Web应用程序将向服务器提交包含与Post关联的标签ID数组的JSON,然后服务器将处理代码中的更新请求。

例如,post_id=1仅提交tag_id=[1,2],因此tag=3需要作为关联表中的关联被删除。

如果删除帖子或标签,我将设置ON DELETE CASCADE

  • posts_tags.post_id
  • posts_tags.tag_id

但是在更新与帖子关联的标签的实例中,更新链接表数据的最佳方法是什么?

选项1:

  • 获取已修改帖子
SELECT * FROM posts_tags WHERE post_id = 1
  • 的所有后贴标
  • 确定添加了哪些标签(并插入到链接表中)
  • 确定哪些标签已被删除(以及从链接表中删除)

选项2:

  • 使用链接表中的post_id删除所有标记
  • 将所有提交的标签插入链接表

选项3:

  • 我没想到的东西:)

随着表的增长,选项2会对索引产生更大的性能影响吗?

编辑:

  • 为清楚起见,实际的帖子和标签数据未​​被更改或删除。这纯粹是关于更新帖子的相关标签
  • 我使用的数据库是PostgreSQL 9.6

1 个答案:

答案 0 :(得分:1)

从性能的角度来看,选项2会很好 - 比选项1好多了,因为你只有一个操作来删除旧的关联,然后是一堆插入语句。在选项1中,您有更多查询(您的第一个查询检索关联,然后删除,如果适用)。

只要你的表在post_id上有一个索引,那么即使在一张巨大的桌子上,delete * from posts_tags where post_id = ?也会闪电般快速。

有另一种选择......

posts_tags表

id| post_id | tag_id | version_id
--------------------------------
1 | 1       | 1      | 0
2 | 1       | 2      | 0
3 | 1       | 3      | 1
4 | 2       | 2      | 0
5 | 1       | 1      | 2
6 | 1       | 3      | 2

在这种情况下,您使用版本控制机制来确定“当前”关联(max(version_id)),因此您永远不必删除任何内容 - 只需插入新行。

在实践中,这可能不会更快,但它确实可以为您节省“删除”查询。