在很多系統設計的時候包括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(N’Bearing Ball’)=
cs_Pname
AND Name = N’Bearing 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值的碰撞。