这将是引入泛型数据模型的好点,或者至少是跨数据模型的泛型类型系统。这个概念是任何事物都有一个入口,甚至是动作、人员、页面、流程等等。当它到位时,您需要一种在这些实体之间创建任意关系的通用方法,使其之间的链接相当容易。您的问题是我为什么要推广更通用的数据模型而不是我们通常使用的超规范化模型的例子之一。
我最常使用的模型是 Topic Maps(尽管该信息可能不是最容易理解我在说什么的),其中没有为每个实体提供一个表格,而是有一个包含所有实体的表格,以及一些额外的处理类型化和它们之间的关系。您不必一直这样做,但也许专门将它用于您的用例。这是大约 10 年前的 an article I wrote about it,以及处理特定 RDBMS 视图的 another one by Marc de Graauw。
回到你的问题。使用主题图的示例首先需要表格;
Topic
-----
id
name
type
meta_date_created
meta_date_created_topic_ref
meta_date_updated
meta_date_updated_topic_ref
meta_date_deleted
meta_date_deleted_topic_ref
Assoc (relationship)
--------------------
id
type
Assoc member
------------
id
topic_ref
role_topic_ref
这将为您提供基础知识(但如果您想全面了解,还有大量的东西需要扩展和实现,例如支持多种类型、持久标识、本体分组,等等,这也是主题地图的一部分),并为您提供 meta_* 字段作为方便的快捷方式,如果这正是您想要的(它们有利于快速搜索:)。
每个人在“主题”中都有一个条目,例如;
id: 4572349857
name: Alexander Johannesen
type: 12341234
meta_date_create: {date}
meta_date_create_topic_ref: 5656
要找出是谁创建了这个用户,请在“主题”中查找 id '5656';
id: 5656
name: Billy Bob
type: 12341234
那是什么类型的呢?在“主题”中查找 id '12341234';
id: 12341234
name: Person
这里的概念基础是系统中的每个“事物”(故意模糊;它可以是您想谈论的任何内容)都有一个条目,包括动作;
id: 34598067
name: Add new user
type: 56987 // another topic called 'Action', for example)
通过所有这些,您的日志基本上是通过“Assoc”表在这些实体之间创建关系;
id: 45673
type: 45685678
这就是协会本身。 'id' 是什么,并不重要,但类型是(你猜对了)'Topic' 表中的另一个实体;
id: 45685678
name: Did action
现在您在“Assoc member”表中填写记录操作的详细信息;
id: {whatever}
topic_ref: 5656
role_topic_ref: 12341234
第一个成员是扮演“Person”角色的 Billy Bob。下一步;
id: {whatever}
topic_ref: 34598067
role_topic_ref: 56987
在这里,“添加新用户”主题扮演“操作”的角色。您可以将此关联扩展到您认为需要的任意数量的项目,例如添加预状态、操作的结果、到目前为止的尝试次数、操作发生的位置(例如,如果它是人们可以执行的功能多页),等等。在 Topic 表中为这些事物创建实体,为它们的关系创建实体,您可以根据需要将其复杂化。
所有这些乍一看可能有点不协调,但它非常灵活,而且您根本不必为将来的扩展更改数据模型。多年来,我一直在使用这种模型构建系统,对此我只有赞美之词。如果您想走这条路,主题属性的单独表格将遵循关联成员的模型。
也许可以为这样的较少表的性能提供一个案例,但根据我的经验,大多数 RDBMS 都非常擅长使用内部连接,这是完成这项工作所需的基本工具(所有作为标识符的字段都是明显的索引候选),好在这也与 NoSQL 的思维方式基本兼容,在您和您的数据以及 SQL 和后端想要使用的技术机制之间创建了足够的抽象。