主键,UUID,RecordKey表,哦我的

时间:2010-11-26 04:26:16

标签: database database-design indexing primary-key uuid

在开发内容管理系统时,我遇到了一些障碍。回到我的数据模型,我注意到一些随着时间的推移会变得更加普遍的问题。

即,我想维护用户记录修改的审计跟踪(更改日志)(甚至会记录用户记录修改)。由于包含了任意数量的模块,我不能为我的主键使用by-table自动增量字段,因为它会在尝试将键保存在单个表中时不可避免地导致冲突。

审计跟踪将保留user_idrecord_idtimestampaction(INSERT / UPDATE / DELETE)和archive(序列化)的记录旧记录的副本)

我已经考虑了一些可能的解决方案,例如在应用程序逻辑中生成UUID主键(以确保跨数据库平台兼容性)。

我考虑过的另一个选项(我确信即使考虑这种方法,共识也是否定的)是创建一个RecordKey表,以维护一个全局自动递增的密钥。但是,我确信有更好的方法来实现这一目标。

最终,我很想知道在尝试实现这一点时我应该考虑哪些选项。例如,我打算允许(至少启动)MySQL和SQLite3存储的选项,但我担心每个数据库如何处理UUID

编辑以使我的问题不那么模糊:使用全局ID是否可以解决我的问题?如果是这样,使用128位UUID(应用程序或数据库生成)我可以在我的表设计中做些什么来帮助最大化查询效率?

3 个答案:

答案 0 :(得分:3)

好的,你碰到了一堵砖墙。而且你意识到db设计实际上存在问题。而且你将来会多次碰到同样的砖墙。而你的未来并不光彩。你想要改变它。好。

但是你还没有做的是,想一想这是什么原因。在你这样做之前,你无法摆脱可预测的未来。如果你做得恰到好处,就不会有砖墙,至少不是这个特殊的砖墙。

首先,您在所有表格上粘贴了Id iot列以强制唯一性,而没有真正理解标识符和自然用于查找数据的键。那是墙壁制成的砖块。对于一个需要考虑的问题,这是一种不加思索的下意识反应。这就是你必须重新访问的内容。

  1. 不要再犯同样的错误。重击GUID或UUID或32字节Id iot列来修复NUMERIC(10,0) Id iot列将无法执行任何操作,除了使db更加丰富,以及所有访问,尤其是加入,慢得多。墙将由混凝土块制成,每小时都会碰到你。

  2. 返回并查看表格,并在数据库中设计它们以成为表格。这意味着您的出发点是没有Surrrogate键,没有Id iot列。完成后,您将只有很少Id列。不是零,不是所有的表,而是很少。因此,墙上的砖块很少。我最近发布了一系列详细的步骤,请参阅:

    Link to Answer re Identifiers

  3. 让一个审计表包含所有表的审计“记录”的理由是什么?你喜欢见砖墙吗?您是否希望db的并发性和速度在一个文件中的Insert热点上出现瓶颈?

    审计要求已经在dbs中实施了40多年,因此用户有一些其他要求不会改变的可能性不是很高。也可以正确地做到这一点。审计表的唯一正确方法(对于Rdb)是每个可审计的实际表具有一个审计表。 PK将是原始表PK加上DateTime(复合键在现代数据库中是正常的)。其他列将是UserId和Action。行本身将是前映像(新映像是主表中的单个当前行)。使用完全相同的列名称。不要把它装成一根巨大的绳子。

    如果您不需要数据(图像之前),则停止录制。无缘无故地记录所有音量是非常愚蠢的。可以从备份中获取恢复。

  4. 是的,单个RecordKey表是怪物。还有另一种保证数据库单线程的方法。

  5. 不要对我的帖子做出反应,我已经从你的评论中看出你做出错误的所有“正确”理由,并保持你的砖墙完好无损。我正在努力帮助你摧毁它们。在回复之前,请仔细考虑几天。

答案 1 :(得分:2)

如何保留每个表的所有record_id本地,并添加另一列table_name(到审计表)以生成复合键?

通过这种方式,您还可以通过table_name轻松过滤审核日志(使用任意UUID或序列号会很棘手)。因此,即使您不使用此解决方案,也可以考虑添加table_name列,以便稍后查询日志。

为了使所有表中的record_id适合同一列,您仍然需要强制所有表对其ID使用相同的数据类型(但您似乎计划这样做) )。

答案 2 :(得分:2)

更强大的方案是创建一个镜像每个表结构的审计表,而不是将所有审计跟踪放在一个位置。 “影子”表模型可以更轻松地查询审计跟踪。