更新闭包表的最佳方法是什么?

lad*_*dge 5 sql sql-server triggers transitive-closure-table

我有一个表使用邻接列表方法(表A)关联记录,另一个表使用闭包表(表B)关联相同的记录.它们都捕获相同的图形,因此它们都需要保持同步.

问题是,更新闭包表的最佳方法是什么?

我认为,有三种选择:

  1. 触发.在A上的INSERT/UPDATE/DELETE中,运行一个计算新闭包的sproc. 缺点:更改为A会导致长时间的同步(锁定?)操作; 可能的死锁(?).
  2. 应用代码.缩小A中的更改以添加/更新/删除方法(例如,存储库模式),并通过调用计算新闭包的sproc来重载它们. 缺点: DB的额外往返; 如果另一个thead同时以相反的方式修改AB,则可能存在完整性问题; 例如,如果另一个应用程序决定修改A而不是B,则可能存在完整性问题.
  3. 背景更新程序.编写一个辅助进程,不断查找A的更新,并对闭包表进行相应的更新. 缺点:复杂(写入和管理的额外服务); 没有同步的窗口.

即使没有"最佳"选项,任何关于权衡的想法都将受到最大的赞赏!

Cad*_*oux 4

如果你的层次结构像我处理过的大多数一样大多是静态的,我可能会触发。实际上取决于更新频率和读取负载。

  • @ladenedge我想得越多,我认为你只需要优化触发器中的闭包编辑,因为如果闭包正在改变,你确实希望读者被阻止。如果您可以允许读者稍微不同步,您可以对整个闭包进行快照构建,并且开始阅读闭包旧版本的读者在组装新版本时不会受到影响。然后可以在单独的过程中删除关闭表中的旧修订。 (2认同)
  • @ladenedge天真地,就像附加'INSERT INTO Closure (RevisionId, ...)',选择'SELECT * FROM Closure WHERE RevisionId = (SELECT MAX(RevisionId) FROM Closure)',每小时清除一次,比如说,用'DELETE FROM闭包 WHERE RevisionId < (SELECT MAX(RevisionId) FROM Closure)' (2认同)