SQL Server HASH函数的妙用以及注意事项

在很多系统设计的时候包括OS,SQL Server很多方面都用到了HASH大大提高了系统的性能,其实我们也可以利用SQL Server的HASH函数实现相同的效果。 比如对长String的Text创建HASH索引快速提高查询能力,可以用来比较表数据差异。

下面有两个例子:

1.用于比较两表的数据异同.

例如找出在T1有,T表没有的记录。

SELECT*

FROMT1

WHERECHECKSUM(*)

NOTIN(SELECTCHECKSUM(*)FROMT)

2.用于创建计算列索引

下列示例显示使用CHECKSUM 生成哈希索引。通过将计算校验和列添加到索引的表中,然后对校验和列生成索引来生成哈希索引。

Create a checksum index.

SET ARITHABORTON;

USEAdventureWorks;

GO

ALTER TABLE Production.Product

ADD cs_Pname ASCHECKSUM(Name);

GO

CREATE INDEX Pname_indexONProduction.Product(cs_Pname);

GO

校验和索引可用作哈希索引,尤其是当要索引的列为较长的字符列时可以提高索引速度。校验和索引可用于等价搜索。


/*Use the index in a SELECT query. Add a second search

condition tocatch stray cases where checksums match,

but the valuesare not the same.*/

SELECT *

FROM Production.Product

WHERE CHECKSUM(NBearing Ball)= cs_Pname

AND Name = NBearing Ball;

GO

 

对计算列创建索引将具体化为校验和列,对ProductName 值所做的任何更改都将传播到校验和列。也可以直接对索引的列生成索引。然而,如果键值较长,则很可能不执行校验和索引甚至常规索引。

但是使用 CHECKSUM()也是有风险的,有可能两个不同的值会产生同样的HASH值,这样比对的数据j就会错误,虽然这样的情况非常少。

比如下面的两个数据不同,但是HASH的结果是相同的。

DECLARE@guid1UNIQUEIDENTIFIER,@guid2UNIQUEIDENTIFIER

SELECT@guid1=’3DB7D309-A8F4-47C4-BA90-0CB458B44CB0′, @guid2=‘EFE7F2C5-19F9-42B9-9C16-21BED41E882B’
SELECT chksum_guid1=CHECKSUM(@guid1),chksum_guid2=CHECKSUM(@guid2)

针对上面提到的问题有些专家给出了下面的解决办法:可以使用CHECKSUM两次,一次正向一次做反向HASH然后把两次的结构加在一起,这样出现碰撞的机会就很少了。

DECLARE@guid1UNIQUEIDENTIFIER,@guid2UNIQUEIDENTIFIER

SELECT@guid1=’3DB7D309-A8F4-47C4-BA90-0CB458B44CB0′, @guid2=‘EFE7F2C5-19F9-42B9-9C16-21BED41E882B’

SELECT chksum_guid1 = CONVERT(BIGINT,CONVERT(BINARY(4),CHECKSUM(REVERSE(@guid1)))+CONVERT(BINARY(4),CHECKSUM(@guid1)))
,
chksum_guid2 = CONVERT(BIGINT,CONVERT(BINARY(4),CHECKSUM(REVERSE(@guid2)))+CONVERT(BINARY(4),CHECKSUM(@guid2)))

经过优化之后我们可以看到HASH的结构已经不一样了,这样就避免的HASH值的碰撞。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值