关于我的问题的第一部分:我最近问自己,为关系数据库中的某些表提供唯一标识符有什么好处和权衡。举个例子,Facebook(FB)图谱API允许使用相同的URL获取不同类型的对象,如“用户”,“事件”,“页面”等,例如https://domain/251906384206返回一个对象键入“Event”,而https://domain/195466193802264返回“Group”类型的对象。
与提供较少“通用”API相比,此方法有什么好处,可以这样使用:https://domain/event/251906384206或https://domain/group/195466193802264。在这种情况下,类似的标识符可能用于不同的对象类型,因为每个对象类型都有它的标识符范围。
关于问题的第二部分:实施全球唯一标识的选项有哪些?
我想到的两个选项是:
使用基于继承的方法(每个表,单个表等)。假设使用了每类表方法(超级表仅包含唯一标识符作为主键,表示对象类型的子表包含与超级表和附加数据相同的标识符),超级表和子表之间需要连接,这似乎很难扩展因为超级表成为瓶颈?
提供包含3列的表格,其中包含
每个对象类型的附加表,包含引用唯一标识符作为外键的列。每个特定于对象类型的表都有自己的主键范围。
这两种方法都允许提供类似上面提到的FB API的通用API。第二种方法允许在内部使用对象表特定的主键,并仅显示全局唯一标识符。但是,如果可以在内部使用全局唯一标识符,则第二种方法也需要连接。
是否有关于全球唯一标识符的优缺点的经验以及实施该标识符的最佳实践?
答案 0 :(得分:0)
“问题很明确,问题已经解决了一半”。
在我看来,你正在混合几个概念。你检查了其他数据库应用程序。但是你似乎更加困惑而不是更多的信息。
您有多个不同类的对象,并且您想知道如何将它们存储在数据库中。这通常由对象关系映射(O.R.M。)的“花式名称”调用。
此外,您希望使用全局唯一标识符(G.U.I.D.)将对象标识为业务/编程对象和表中的行。
此外,您还想使用G.U.I.D.识别某种类别或对象。
假设您正在构建应用。你有几个对象的地方。有几类对象,例如“用户”,“事件”,“页面”等。您可以拥有相同类/类型的多个对象,但是您需要一种方法来识别彼此。来自密歇根州的“John Doe”,来自昆士兰州的“John Doe”。假设您的对象将使用G.U.I.D。
类型的属性因此,我们假设你为每个类创建一个表(“user”为“Users”,表标准id。是单数和小写,altought你可以忽略它,“event”表示“事件”,等等)。每个表都有几个字段,表示每个对象的属性。因此“user”将具有类似“user_key GUID”的字段,并且可能具有“user_name varchar(100)”和“user_birthdate datetime”。其他表也是如此。
我使用过“supertable”,但只针对一个非常具体的,不常见的应用程序。我不认为你需要一个混合“用户”,“事件”,“页面”的表。我有一个案例,我们有一个超级“客户”,加上“公司”和“人”子表与特定的附加字段。有时,我们必须检查所有客户的销售情况,并与“客户”表进行联接。有时,我们必须为产品提供企业折扣,并浏览“公司”子表格。
如果您希望此Generalization /“IS a”具有超级功能,则不需要为超级主键和详细信息表主键设置不同的字段,可以使用相同的类型。
我建议不惜一切代价避免使用复合/复合键(“主键”加上“其他”字段),使用单个字段主键。我还建议指定G.U.I.D.密钥使用编程,而不是在数据库中。
G.U.I.D.使用更多的内存和磁盘空间,而不是整数键,但是,它非常快速且容易获得非常难以复制的密钥。
同样,您提出的问题更多的是如何在数据库中表示对象,而不是使用G.U.I.D。
答案 1 :(得分:0)
您提出的两种实现全局标识符的方法都涉及大表的连接以及数据库中记录数量的有效加倍(每个对象本身都存在,但父级/记录的全局ID也是如此)。
我觉得在应用程序/数据访问层中强制执行全局ID会更好。 这可以通过强制执行每个特定类型的对象的ID仅来自可能ID的子集来完成。例如,您可以保留所有ID的最后/前x位以指定对象类型。 ID的剩余部分将是“实际ID”。
如果您在为spefic表分配ID时害怕出错,则可以添加一个检查约束来强制ID正确(例如ID <4000和ID> 10000)。 如果您担心在其标识符中浪费了对象类型的位/字节,则只能在数据库访问API中公开全局ID,这会将对象的ID(实际存储在表中)与其类型ID连接起来(派生自对象类型)。