【发布时间】:2013-01-05 04:52:04
【问题描述】:
我正在尝试快速确定两组时间表是否相同,并生成一个可以引用这些独特时间表的密钥。我最初尝试使用 HASHBYTES,但很快发现您只能散列 8000 个字符,而且我有大量的日期时间,它们连接时超过 8000。
所以,我尝试使用 Checksum 和 Checksum_Agg,因为它们似乎是为这类事情而设计的。我知道校验和更有可能生成非唯一值。但是我需要将它们相互比较的范围/背景太窄了,我想我可以侥幸逃脱。
不幸的是,经过一些测试后,我了解到我可以在 4 行日期时间数据中找到校验和“冲突”!我觉得这有点奇怪,并发现了碰撞的模式。
下面是一个演示该问题的示例脚本:
声明@Rows 表 ( [GroupId] 整数, [开始日期] 日期时间, [结束日期] DATETIME ) --Group1 插入@Rows 值(1、'2013-01-20 01:00:00.000'、'2013-01-20 01:20:00.000') 插入@Rows 值(1,'2013-01-20 01:20:00.000','2013-01-20 01:40:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 01:40:00.000', '2013-01-20 02:00:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:00:00.000', '2013-01-20 02:20:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:20:00.000', '2013-01-20 02:40:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:40:00.000', '2013-01-20 03:00:00.000') --Group2 插入@Rows 值(2、'2013-01-21 01:00:00.000'、'2013-01-21 01:20:00.000') 插入@Rows 值(2、'2013-01-21 01:20:00.000'、'2013-01-21 01:40:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 01:40:00.000', '2013-01-21 02:00:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:00:00.000', '2013-01-21 02:20:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:20:00.000', '2013-01-21 02:40:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:40:00.000', '2013-01-21 03:00:00.000') 选择 [ChecksumAgg1] = CHECKSUM_AGG([CheckSum]) 从 ( 选择 [校验和] = 校验和([开始日期],[结束日期]) 来自@Rows 其中 GroupId = 1 ) G1 选择 [ChecksumAgg2] = CHECKSUM_AGG([CheckSum]) 从 ( 选择 [校验和] = 校验和([开始日期],[结束日期]) 来自@Rows 其中 GroupId = 2 ) G2结果是:
ChecksumAgg1:5681728
ChecksumAgg2:5681728
这两个日期系列之间的唯一区别是它们相隔 1 天。但是它们会生成相同的校验和!但仅当存在 偶数 行时。如果您取消注释 Group 1 中的 INSERT 和 Group 2 中的一个 INSERT,您将获得两个不同的校验和。但是然后取消注释另一对,您将获得另一对!
最后我有两个问题。我很想更多地了解它是如何工作的,以及为什么这种模式似乎会影响一个相当可预测的校验和值。更重要的是,我想知道是否有更好的方法来创建大量数据的“指纹”。我知道我不能保证这个哈希是全球唯一的,但我显然需要比校验和更好的东西。
我能够对校验和计算进行某种技巧的一种方法是在 Datetime 上执行 HASHBYTES,然后将其提供给 Checksum 函数。通过这种方式,校验和被提供的值比一组具有相似外观差异的日期看起来更随机。但这样就够了吗?
编辑 - 这里只是更多的上下文。
基本上,我有一个拥有大量日程数据的系统和一个在特定时间对这些日程感兴趣的单独系统。例如,多个用户可能会看到这个复杂时间表的某个部分的特定版本,并希望添加一些元数据(可能是他们的批准状态、注释或其他内容)。如果某些外部来源对任何单个日期时间进行了更改,则需要断开此链接,因为它不再是相同的时间表!
有许多不同的系统可以对核心计划数据进行更改,这就是为什么我很难将这种担忧提升到代码级别,以便以某种方式对其进行管理和“规范化”为代表每个快照的实体某种方式。我必须在一百万个地方安装钩子来监听变化,然后清理任何指向时间表的东西。
【问题讨论】:
标签: sql-server hash checksum