【问题标题】:SQL Server CHECKSUM function issueSQL Server CHECKSUM 函数问题
【发布时间】:2018-10-05 16:53:43
【问题描述】:

谁能给我解释一下,也许可以提出一个更好的方法。

为什么 checksum(0.0280) = checksum(-0.0280) ? 投射到浮动可以解决它,但我不愿意这样做,我宁愿找到解决这个问题的方法。

LE:我试图让事情保持简单,就像这里的大多数问题一样,这是在生产中出现的东西,并且放置整个数据库结构有点矫枉过正。 我会尝试更好地解释它。我有一些动态结构表(在终端用户通过 Web 应用程序控制结构的意义上是动态的),它们具有以下粗略结构:Id (int)、StartDate、FKey1 (nvarchar)、Value1(十进制或 nvarchar 或 int),值 2 ... 值 N。

这个表可以填充(再次,由最终用户)冗余数据(数百万行),在一些计算过程中,我想整理这个表,只留下相关信息。整理它的方法是删除连续的相同行(日期除外)。为了性能,我想避免单独检查每一列,所以 CHECKSUM 派上用场了,因为它还支持多列作为输入。

【问题讨论】:

  • “解决”是什么意思?你想做什么?
  • sql server 中的小数,还是个迷宫!如果您不指定数据类型(十进制或浮点数),您的结果大多是不正确的。例如,如果您在没有强制转换的情况下执行SELECT (1/100),您将得到一个 0,将其中一个强制转换为十进制或浮点数,您将得到 0.01。所以如果你想直接在 T-SQL 中写一个数字,你需要指定数据类型。 (所以我假设 0.0280 被读取为 0 对于校验和,并且转换为浮点数或小数将修复它。
  • 我添加了更多细节
  • 为了性能,我想避免单独检查每一列,所以 CHECKSUM 派上用场了,因为它还支持多列作为输入。正确索引的列肯定会胜过非索引校验和列。其他人提出了很多建议,但出于性能原因,它们似乎都不适合。
  • 一种常见的模式是首先使用校验和来大大减少匹配的数量,然后根据该结果,实际比较各个列以解决冲突

标签: sql-server checksum


【解决方案1】:

如果您认为每个可能的 CHECKSUM 都只有一个可能的值,那您就错了。

来自documentation

如果表达式列表中的至少一个值发生变化,则列表 校验和可能会改变。但是,这不能保证。 因此,要检测值是否已更改,我们建议使用 仅当您的应用程序可以容忍偶尔遗漏时才使用 CHECKSUM 改变。否则,请考虑改用 HashBytes。使用指定的 MD5 哈希算法,HashBytes 对于两个不同的输入返回相同结果的概率远低于 CHECKSUM。

如果你想进一步研究它,你可以谷歌CHECKSUM collisions

【讨论】:

  • 我可以容忍碰撞......但是这个太接近了。
  • 所以试试 HashBytes,就像文档建议的那样。
  • 感谢您的建议,不幸的是,HashBytes 只接受 varchar、nvarchar 或 varbinary,我需要我的解决方案不需要强制转换,因为这些表非常大。
  • 我最终使用了 HashBytes,但有一个技巧让它适用于我的场景:HashBytes('SHA1', (select Column1, Column2, Column3 for xml raw))
【解决方案2】:

使用散列函数(如 CHECKSUM)总会有发生冲突的风险。

您可以尝试另一个(较慢的)哈希函数(如@TabAlleman 提到的 HashBytes),或者您可以尝试一些可能比 HashBytes 表现更好的自制尝试(但这应该经过测试),并且更符合您的预期你期望的数字是多少。所以这是一个权衡:性能与碰撞风险。这里有 2 次这样的自制尝试,对于除符号外相等的数字会给出不同的结果。请注意,这些变体也会产生冲突,但最有可能是因为它们的符号之外的其他差异。

select checksum(.028, floor(.28))
select checksum(-.028, floor(-.28))

select checksum(.028) + sign(.28)
select checksum(-.028) + sign(-.28)

当您说可以通过强制转换为浮点数来解决它,但仍然不想这样做时,我想知道这是否出于性能考虑。如果是这样,我不确定我的变体是否会比转换为浮点数更好。自己测量一下吧:-)

【讨论】:

  • 感谢您的回答。我会尝试一下发言权建议。我不愿意考虑性能,我不想更改表的数据类型,因为这需要在任何地方进行调整。我在问题中添加了更多细节,以便更好地了解我的实际用例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2014-12-02
  • 2020-06-23
相关资源
最近更新 更多