首先,我使用的是Postgres 9.1。
我有一个名为filepaths的表和其他表,这些表的行指向其相应文件路径的id。是否存在一种用于引用计数文件路径的通用设计方法,以便在删除其他行并且不再引用特定文件路径行时,也可以删除它?
示例:
[filepaths]
1 | c:\windows\system32\test.exe
2 | c:\windows\calc.exe
[events_2011_08_30]
[1][timestamp][other data] [ filepaths = 1]
[2][timestamp][other data] [ filepaths = 2]
[events_2011_08_31]
[1][timestamp][other data] [ filepaths = 1]
所以我将把数据存储在表中进行分区,并且我想在旧表超过30天时删除旧表(仍然会将它们存档)。在上面的例子中,我们假设只有那两个events_表。如果我删除2011_08_30,我想要一种方法来知道没有任何东西指向文件路径'2'并因此删除它,但是知道一行仍指向文件路径'1'并因此保留它。
有任何想法,建议等吗?我相信我读过的一些策略,至少对于postgres和触发器,仍然有关于哪个线程首先锁定主键列和其他相关问题的竞争条件。
谢谢!
答案 0 :(得分:2)
首先,我要挑战每个日期在一个表上划分数据的愿望。相反,我建议您在表格中添加一个名为effective_date
或类似的列。
就filepaths
的引用计数而言,可以通过多种方式实现,但为了确保代码的封装,我建议采用以下两种方法之一......
<强> 1。存储过程API
通过确保通过存储过程处理所有 INSERT,UPDATE和DELETE操作,您还可以在filepaths
上封装引用计数器的递增和递减。然后,没有用户/登录需要访问表以进行写入活动,而只需使用存储过程。
<强> 2。触发器强>
可以在每个events
表上创建一个触发器,以封装引用计数器递增和递减代码。每当修改表内容时,触发器都会触发并传播业务逻辑的后果。
许多人回避触发器,因为他们觉得它们被隐藏起来,如果过度使用会产生复杂的相互作用。但是,我认为它们非常有用。
在任何一种情况下,通过只有一个表而不是多个表来简化一切。
此外,大多数SQL设计模式不会将“删除表格”视为“常规业务”操作。在我看来,创建或删除表应该被视为设计更改,而不是数据活动。
答案 1 :(得分:1)
您不需要引用计数。 (你可以使用触发器实现它,如果你真的想要它) 你想要的是一个外键[约束]
清理文件路径表的最简单方法是使用NOT EXISTS结构,例如
DELETE FROM filepaths fp
WHERE NOT EXISTS ( SELECT * FROM events ev where ev.file_id = fp.file_id)
AND NOT EXISTS (SELECT * FROM events_version_xxx ev where ev.file_id = fp.file_id)
AND NOT EXISTS (SELECT * FROM events_version_yyy ev where ev.file_id = fp.file_id)
...
;
这太丑了。但数据库模型也很难看。