繁体   English   中英

确定性代理键

[英]Deterministic Surrogate Key

我有一个带有整数标识列的表作为其他两个列(int 和 datetime)的代理键。 为了让这个键的值在测试和生产环境中保持同步,我想制作一个触发器,将代理键设置为某个确定性的值而不是自动生成的身份(在这种情况下是自然键的散列) . 据我所知,权衡是我引入了冲突的风险(可以通过将代理列更改为 bigint 来抵消)。

CREATE TRIGGER dbo.TRG_TestTable_SetID ON dbo.TestTable 
INSTEAD OF INSERT
AS 
BEGIN

    insert into dbo.TestTable (ID, IntKey, DateKey, MoreData)
    select convert(bigint, hashbytes('md5', convert(binary(4), IntKey) + convert(binary(8), DateKey))), 
        IntKey, DateKey, MoreData
    from inserted
END

从设计的角度来看,这是一个很好的解决方案吗? 它仍然会比使用自然组合键作为主键表现更好吗?

编辑:自然键中的 int 是另一个表的外键,它是 guid 和 varchar 的代理键。 因此,该表上的“自然键”替代方案将是 guid、varchar 和 datetime 的相当丑陋的组合。

出于类似的原因,我之前使用过类似的技术并取得了很好的成功。 为了获得您想要的确定性质量,您可以尝试将复合自然键列值强制转换为字符串,将它们字符串连接在一起,然后从中生成一个 MD5 哈希值以用作您的确定性主键。

一些考虑:

  • 区分大小写。 除非您的某些业务键被设计为区分大小写,否则最好在您的系统中建立一个约定,首先将字母大写或小写,因为 'a' 与哈希函数的 'A' 不同. 如果您从可能是手动用户键入的数据创建密钥,这有助于避免出现问题。 例如,如果用户键入项目编号“itm009876”而不是“ITM009876”,并且您的各种源系统不够健壮,无法在存储它们之前符合该值。
  • 字符串强制:确保以有意义且非常具体的方式将值强制转换为字符串。 例如,使用 ISO 日期和日期时间加上时区,或者在强制转换为字符串之前将日期和日期时间转换为 Unix 时间戳整数
  • 字符串分隔符。 在串联之前在字符串之间使用一个好的字符串分隔符,例如';'。 (例如,A+CB 的字符串连接不应与 AB+C 相同)
  • 将哈希存储为二进制:如果可能,将 MD5 哈希作为 16 字节二进制值存储在表中,并使用 HEX() 函数以人类可读的格式显示它。 将 MD5 散列存储为二进制文件使用的空间量正好是存储 32 字节十六进制字符串所需空间量的一半,这对于查找和连接的性能具有优势,因为它既更短又完全避免了在特殊字符串比较上浪费的任何可能的周期逻辑。

优点

  • 有时可以避免行数据的意外重复
  • 可以避免不必要的往返必须生成或检索序列或 UUID 代理密钥的单一权限。
  • 最终用户使用单列键更容易。
  • 下游开发人员可以更轻松地编写 SQL、生成 url 等以使用单列键。
  • MD5 很老而且很成熟,因此大多数 DBMS 都很好地支持它作为 SQL 函数,因此您也可以根据需要在那里使用计算它们,而无需第三方扩展。
  • 使用 MD5,碰撞极为罕见。 与发生碰撞相比,您的数据中心更有可能被流星摧毁,即使有数千亿行和单个表也是如此。 如果您在 Google 上搜索一种使用散列键的流行方法:“数据保险库散列键”,那么网上会有很多关于此的激烈讨论。

缺点

  • 当然,MD5 在理论上仍然可能发生碰撞。 很多机构对此还很犹豫。 因此,如果您必须在散列空间上有更多字节,并且您可以忍受连接和索引更新期间潜在的性能损失,您总是可以选择更长的 SHA 散列。
  • 一代是复杂的。 您必须选择并记录生成复合密钥散列的算法,并与组织中的其他开发人员进行良好的沟通。 只要确保每个人都以同样的方式去做。
  • 由于散列的非顺序性质,它们在某些情况下查询效率低下,例如在聚簇索引表中。 小心这一点,因为某些 DBMS 使用聚集索引作为默认值 - 或者甚至可能没有任何其他选项 - 例如 MYSQL 的 InnoDB。 堆表通常更好,例如在 PostgreSQL 和 Microsoft SQL Server 中支持/默认。

(抱歉有任何错别字和语法错误。我正在手机上写这个。我会尝试稍后回来清理它。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM