日志表中的外键......好还是坏?

时间:2013-07-09 08:51:40

标签: sql design-patterns database-design logging

这是一个设计问题。

假设我有一个用户表{UserKey,UserName},我正在记录一些用户Activity。所以在日志表{UserKey,Activity}中,我有一个UserKey列。现在,将日志表中的UserKey作为用户表的Foriegn键是个好主意吗?

据我所见,

Pros(ForiegnKey):没有悬空记录。

缺点(ForiegnKey):硬删除是不可能的,除非我也删除了日志,这是非常糟糕的。

你的建议是什么?我还缺少什么?

5 个答案:

答案 0 :(得分:3)

  

缺点(ForiegnKey):硬删除是不可能的,除非我也删除了日志,这是非常糟糕的。

首先,这并非“明显”糟糕。这只是处理悬空记录的一种方法。顺便说一句,您不必从客户端代码中执行此操作 - 您可以通过ON DELETE CASCADE参考操作自动执行此操作,并让DBMS为您执行此操作。

另一种方法是使用NULL-FK(并且可能使用ON DELETE SET NULL)。


您根本无法保留与数据库中不再存在的用户关联的记录。悬空记录可能会保留用户密钥,但该密钥不再具有意义,甚至可以被新用户重用(如果您使用自动递增ID,则可能不太可能)。

但是你可以“退休”用户(例如通过在用户表中设置一个标志),并且仍然保留她的所有记录,并且可能有一个后台进程来清理已经太旧而不再重要的退役用户。 / p>

在任何情况下,FK都是 防止悬空记录的方式,我非常不愿放弃它。通过适当的索引,应该没有性能问题,如果您认为有,请度量并在做其他任何事情之前确认它确实存在...

答案 1 :(得分:1)

正如您自己所看到的,这两种方法都有利有弊。就个人而言,我不希望将外键放在日志表中,因此您只有在添加新记录时才能写入表,并且可以针对追加优化日志表的存储。作为一项好处,您可以使用原始ID维护有关已删除项目的日志记录。

答案 2 :(得分:1)

我建议不要FK (1)虽然我们可以创建一个FK关系,但它并不一定是真正的关系。手段,它的意义不大,用户有许多使用事件...事件有一个单独的目的。 (2)我们可以允许匿名/访客用户,他们也应该记录事件!

答案 3 :(得分:1)

  

缺点(ForiegnKey):硬删除是不可能的,除非我也删除了日志,这显然是坏的。

物理删除Users但不记录日志? 我认为这样的概念需要重新思考和优先排序。

在删除之前,我会考虑hide {/ 1}}。

如果你不知道是谁做了什么,那么保留日志是什么意思。

如果不是删除user你存档它们,FK实际上并不是一个FK用于支票,而只是一个建议。

答案 4 :(得分:0)

您的问题有多种解决方案。您可以1. logically delete用户并保持数据完好无损,也可以在日志表中2. log the user key only

如果您有少量/中等数量的用户,第一个解决方案很棒。但它有性能缺点:如果应用程序增长并且用户数量变大,那么在Users表中,您仍然会有非活动用户,这些记录会降低数据库响应速度(例如,在登录操作期间)

第二种解决方案很好,无论您的应用程序在一段时间内拥有多少用户。但是您将丢失您删除的用户的数据。因此,您将不知道5年前制作某些活动的已删除用户的详细信息。

还有第三个解决方案:3. using table 'UserArchive' 这个结合了第一个解决方案的优点,并避免了第二个解决方案的问题。 您可以构建一个名为UserArchive的新表,该表将包含应用程序中存在的所有用户的数据。将Log表与UserArchive表链接可以为evey用户提供数据,即使用户表中的用户不再存在,也会创建一些Activity。

当用户注册时,您可以在Users表中添加所需的详细信息,并在UserArchive表中添加一些重要(或全部)详细信息。 (注意数据冗余,如果这对您的数据库好或坏,由您决定) 当用户想要删除帐户时,您可以在Users表中自由进行硬删除,因为重要(或所有)详细信息存储在UserArchive中。

建议:Users表不应与UserArchive连接,因为从逻辑的角度来看,它不是必需的。

由您决定哪种解决方案最适合您的应用。