如何在多对多链接 table 中更新数据?

How to update data in a Many-to-Many linking table?

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

posts Table

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

标签Table

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

posts_tags table

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

一个Post可以有很多标签,一个标签可以关联很多Post。

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

例如,post_id=1 仅与 tag_id=[1,2] 一起提交,因此 tag=3 需要作为链接中的关联删除 table。

如果 Post 或标签被删除,我会在

上设置 ON DELETE CASCADE

但是,在更新与 post 关联的标签的实例中,更新链接 table 数据的最佳方式是什么?

选项 1:

选项 2:

选项 3:

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

编辑:

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

只要您的 table 在 post_id 上有索引,那么 delete * from posts_tags where post_id = ? 就会快如闪电,即使在巨大的 table.

上也是如此

还有一个选择...

posts_tags table

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

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

在实践中,这可能不会更快,但它确实为您节省了 "delete" 查询。