【发布时间】:2018-06-20 14:20:05
【问题描述】:
在 SQL Server 中,是否可以使用特定数据作为输入值来生成 GUID。例如,
DECLARE @seed1 VARCHAR(10) = 'Test'
DECLARE @seed1 VARCHAR(10) = 'Testing'
SELECT NEWID(@seed1) -- will always return the same output value
SELECT NEWID(@seed2) -- will always return the same output value, and will be different to the example above
我知道这完全违背了 GUID 的观点,因为 ID 不会是唯一的。我正在寻找一种基于特定标准(@seed 值)检测重复记录的方法。
我尝试使用HASHBYTES 函数生成VARBINARY 字符串,但是使用VARBINARY 在表之间连接似乎非常慢。我希望找到一个更有效的类似替代方案。
编辑:详细了解我为什么要实现这一目标。
我正在寻找一种快速有效的方法来检测两个表上存在的重复信息。例如,我有名字、姓氏和电子邮件。当这些被连接起来时,应该可以用来检查这些记录是否存在于表A和表B中。
可以简单地加入这些字段并提供正确的结果,但是速度很慢。因此,我希望找到一种将数据转换为诸如 GUID 之类的东西的方法,这将使连接更加高效。
【问题讨论】:
-
您似乎已经决定了做某事的方法,现在正在就如何做某件事寻求帮助。您能否添加一些代表您的情况和所需输出的虚拟数据?很可能有更简单的解决方案可供使用
-
我正在寻找一种基于特定标准检测重复记录的方法,您能否扩展此要求?这可能是 XY 问题。
-
GUID 实际上是
BINARY(16),并且加入的速度也差不多。在散列时,您的VARBINARY值最终可能会更大,但这可以通过采用子字符串来“解决”(以增加冲突概率为代价,但这对于正确的加密散列来说不是问题)。如果结果仍然太大/太慢,最好在查找表上使用IDENTITY或SEQUENCE,缺点是需要在调用者之间同步,但这通常会被更好的方法所抵消加入 4 字节整数时获得的性能。 -
现在您已经解释了为什么需要它,我想说 CHECKSUM 或 HASHBYTES 函数正是您所需要的;它们专为您所想的目的而设计。 (请注意,两个不同的项目总和为相同值的可能性很小,因此您可能应该保留原始匹配条件,但只要校验和值被索引并在您的查询中使用以及 , SQL Server 应该足够聪明,可以在进行精确比较之前使用该索引来过滤结果。)从概念上讲,您正在寻找的绝对是“散列”。
-
如果您只是想加快连接速度,您甚至不需要较短的值是唯一的——只要它们足够唯一来加速索引就足够了搜索(
WHERE hash1 = hash2 AND mycolumn1 = mycolumn2,第一部分将允许大部分加速)。即使CHECKSUM也可以用于此目的,尽管它的碰撞率对于许多真实世界的数据来说是可怕的,你可以使用(比如)CONVERT(INT, SUBSTRING(HASHBYTES(...), 1, 4))做得更好。
标签: sql sql-server hash sql-server-2014 guid