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

3

这是一个关于设计的问题。

假设我有一个用户表{UserKey, UserName},并且我正在记录一些用户活动。因此,在日志表{UserKey, Activity}中,我有一个UserKey列。现在,在日志表中,将UserKey作为外键与用户表进行关联是否是一个好主意?

据我所见,

优点(外键):没有悬挂记录。

缺点(外键):除非我也删除日志,否则无法进行硬删除,这显然很糟糕。

你有什么建议吗?我还漏掉了什么?

5个回答

4

Cons(ForiegnKey): 如果我不删除日志,硬删除将不可行,这显然是不好的。

首先,这并不是“显然”不好的。这只是处理悬空记录的一种方式。顺便说一下,您不必从客户端代码中执行它 - 您可以通过ON DELETE CASCADE引用操作自动化它,并让数据库管理系统为您执行。

另一种方法是具有可为空的FK(并可能使用ON DELETE SET NULL)。


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

但是您可以“退休”用户(例如,在用户表中设置标志),并仍然保留她的所有记录,并且可能有一个后台进程清理太老而不再重要的退休用户。

无论如何,FK是防止悬空记录的方法,我非常不愿放弃它。通过适当的索引,不应该有性能问题,如果您认为存在问题,请测量并确认确实存在问题再采取其他行动...


2

Cons(ForiegnKey): 除非我也删除日志,否则无法进行硬删除,这显然是不好的。

对于Users进行物理删除,但不删除日志?我认为这样的概念需要重新思考和优先考虑。

在删除之前,我会考虑将user隐藏起来。

否则,如果您无法告诉谁做了什么,保留日志有什么意义呢。

如果您归档而不是删除users,则FK实际上不是用于检查的FK,而只是一个建议。


1
日志应该被整理清除,而非删除。如果用户已不再存在于系统中,则仍应显示旧用户条目的日志,可能作为简单字符串。我总是主张反规范化、重复记录日志,在时间上,它更有意义。历史就是历史,因为希特勒不再存在并不意味着第二次世界大战没有发生。 - Tiju John

1

正如你自己所看到的,这两种方法都有优点和缺点。个人而言,我倾向于不将外键放在日志表中,这样只有在追加新记录时才会写入表中,并且可以针对追加进行日志表存储的优化。作为一个好处,你可以维护关于已删除项目及其原始ID的日志记录。


1
我建议不使用外键(no-FK) (1)虽然我们可以创建外键关系,但实际上并不需要这种关系。也就是说,说一个用户有很多用户事件并没有太多意义...事件有其独立的目的。 (2)我们可以允许匿名/游客用户,他们也应该记录事件!

0

你的问题有多种解决方案。你可以选择1. 逻辑删除用户并保留数据,或者你可以在日志表中2. 仅记录用户键

如果用户数量较少/中等,第一种解决方案非常好。但它也有性能缺陷:如果应用程序增长并且用户数量变得更大,则在用户表中仍将有未活动的用户,这些记录将减慢数据库响应(例如,在登录操作期间)。

第二个解决方案无论您的应用程序随时间拥有多少用户都很好。但你将失去已删除用户的数据。因此,您将不知道五年前执行某些活动的已删除用户的详细信息。

还有第三个解决方案:3. 使用表“UserArchive”。这个解决方案结合了第一个解决方案的优点,并避免了第二个解决方案的问题。你可以构建一个新表叫做UserArchive,它将包含您的应用程序中存在的所有用户的数据。将Log表与UserArchive表联系起来,即可获得每个进行了某些活动的用户的数据,即使该用户在Users表中不存在。

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

建议:Users表不应与UserArchive连接,因为从逻辑上讲这是不必要的。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接