今天特地查了一下SQL Server下的校检函数有哪些。原本我只是在工作中用过一个CHECKSUM,今天特地学习了一下才发现原来还有其他的校检函数。

这里找到了别人对于SQL SERVER下这几个校检函数的学习总结,借此机会学习下别人的学习成果

http://bbs.51cto.com/thread-1145105-1.html

CHECKSUM和BINARY_CHECKSUM

  • CHECKSUM和BINARY_CHECKSUM都是可以针对表中一行的单列或者多列又或是表达式生成数据类型为INT的校检值。
  • 不同的地方是BINARY_CHECKSUM是转成了二进制后生成的校检值。
  • 并不是所有的数据类型都可以用到CHECKSUM或BINARY_CHECKSUM上的。BINARY_CHECKSUM 在计算中忽略具有不可比数据类型的列。 不可比数据类型包括 text、ntext、image、cursor、xml 和不可比公共语言运行库 (CLR) 用户定义的类型。
  • MSDN上讲到BINARY_CHECKSUM 可用于检测表中行的更改。但是也提到BINARY_CHECKSUM(*) 将为大多数(但不是全部)行更改返回不同的值,并可用于检测大多数行修改。
  • 因为校检值是一个INT,根据INT的数值分布[-2147483648,2147483647],如果某长表中的行数大于2亿估计就会出现重复的情况了。这点在以前工作中就碰到过。
  • CHECKSUM和BINARY_CHECKSUM的不同是:1)CHECKSUM是不区分大小写。它认为Jerry和jerry是同样的校检值;2)如果两个表达式具有相同的类型和字节表示,那么对于 BINARY_CHECKSUM 将返回相同的值。例如,BINARY_CHECKSUM 对于“2Volvo Director 20”和“3Volvo Director 30”将会返回相同的值。这段参考了http://ultrasql.blog.51cto.com/9591438/1607407

CHECKSUM_AGG

这个是个聚合函数。返回组中各值的校验和。 将忽略 Null 值。 后面可以跟随 OVER 子句。CHECKSUM_AGG 用于检测表中的更改。如果表达式列表中的某个值发生更改,则列表的校验和通常也会更改。 但只在极少数情况下,校验和会保持不变。很多情况下这个函数应该是用来检测表的数据是否有改动或者表的某个字段的数据是否有发生改动。

HASHBYTES

HASHBYTES是一个加密算法函数,用来对数据进行加密、或校验。它会返回其在 SQL Server 中的输入的 MD2、MD4、MD5、SHA、SHA1 或 SHA2 哈希值。它可以是作为加密功能和强度上更加强大的函数。可以用MD5替换CHECKSUM或BINARY_CHECKSUM避免重复。但是性能上可能有所下降。当然了,比起SHA-256这种加密强度极强的算法,MD5还是完全能接受的。

---------------------------------------------------- Update on 11/21/2015 ---------------------------------------------------------

这些函数的一个作用就是用于数据校验。举一个非常常用的场景 -- 哈希索引。在一些数据仓库(ETL)系统或者一些做EDI的系统里面,source传一些文件给到我们,我们再对这些文件进行处理(加载)。这当中就需要队列表。每次线程扫描目录的时候要能够知道文件是已经在队列表里面,不需要再进一次队列。那么我们就必然需要对“文件完整路径”和“修改时间”建立一条索引来加快每次检索的速度。而我们都知道SQL Server对索引的长度是有限制,最长不得超过16个字段或者900个字节长度(详细参考MSDN的文章)。像“文件完整路径”这种值肯定存在超过900个字节长度的可能性。解决办法就是对“文件完整路径”和“修改时间”建立一条哈希索引,因为哈希索引的长度即便是最长是SHA-256也不过64个字节,相比普通索引还是小得多的。需要说明,长度越长的哈希索引在加密过程所需要消耗的CPU越多,但是它会产生的哈希值冲突的可能性就越低。这个需要你根据对表具体的数据行增长和作为索引字段的个数的情况而选择合适的检验函数。

但是有一点还是需要肯定的是,像上面这样的例子尽量是不要选择CHECKSUM,原因是CHECKSUM返回的是一个INT类型的值。我们都知道INT支持的最大值不过是2亿多。这里做一个测试,在10万行的时候其实已经出现了哈希值冲突的情况了。这种情况选择MD5或者SHA-128/SHA-256。

USE [JerryDB]
GO IF OBJECT_ID('dbo.ChecksumCollision') IS NOT NULL
DROP TABLE dbo.ChecksumCollision
GO CREATE TABLE dbo.ChecksumCollision(col1 NVARCHAR(4000),
checksum_col AS CHECKSUM(col1))
GO INSERT dbo.ChecksumCollision(col1)
SELECT CAST(CHECKSUM(NEWID()) AS VARCHAR(100))
FROM [dbo].[Numbers]
WHERE [Num] <= 100000 select * from (
select col1, checksum_col, count(checksum_col) over (partition by checksum_col) as cnt
from dbo.ChecksumCollision) t
where cnt > 1
order by checksum_col

上面代码的运行结果

下面测试测试一下用HASHBYTES('MD5',XXX)的情况,

USE [JerryDB]
GO IF OBJECT_ID('dbo.ChecksumCollision') IS NOT NULL
DROP TABLE dbo.ChecksumCollision
GO CREATE TABLE dbo.ChecksumCollision(col1 NVARCHAR(4000),
checksum_col AS HASHBYTES('MD5',col1))
GO INSERT dbo.ChecksumCollision(col1)
SELECT CAST(CHECKSUM(NEWID()) AS VARCHAR(100))
FROM [dbo].[Numbers]
WHERE [Num] <= 1000000 select * from dbo.ChecksumCollision
where checksum_col in (
select checksum_col
from dbo.ChecksumCollision
group by checksum_col
having count(distinct col1)>1)
order by checksum_col

上代码返回的结果

接下来来实现上面说的那个检查文件队列的例子

接下来我们建立一条索引

create index ix_ChecksumCollision_checksum_col on dbo.ChecksumCollision(checksum_col);

然后找一行来测试

然后试下运行下面的代码利用哈希索引找到改行

select * from dbo.ChecksumCollision
where checksum_col = hashbytes('MD5',N'')

结果

观察执行计划,确定上面建的哈希索引是被使用到的

有1点需要说明的是:

不管是MD5或者SHA都是依赖数据类型来产生哈希值的,这就意味着N'Jerry'和'Jerry'产生的哈希值其实是一同的。像上面的查询语句如果改成这样则不会返回任何结果

关于性能,参考中的第三个链接有人对这些函数都做了性能比较。应该说SHA-512是最慢这点没错,毕竟用了整整64个字节来产生校检值。MD5倒是稍稍比CHECKSUM慢上一点而已。

参考:

http://www.brentozar.com/archive/2013/05/indexing-wide-keys-in-sql-server/

https://technet.microsoft.com/zh-cn/library/ms174415(v=sql.105).aspx

http://pastebin.com/iF4XBSab

SQL Server ->> 校检函数CHECKSUM、CHECKSUM_AGG、BINARY_CHECKSUM和HASHBYTES的更多相关文章

  1. sql server中常用方法函数

    SQL SERVER常用函数 1.DATEADD在向指定日期加上一段时间的基础上,返回新的 datetime 值. (1)语法: DATEADD ( datepart , number, date ) ...

  2. SQL Server 内置函数、临时对象、流程控制

    SQL Server 内置函数 日期时间函数 --返回当前系统日期时间 select getdate() as [datetime],sysdatetime() as [datetime2] getd ...

  3. SQL Server:字符串函数

    以下所有例子均Studnet表为例: 1. len():计算字符串长度 len()用来计算字符串的长度,每个中文汉字或英文字母都为一个长度 select sname, len(sname) from ...

  4. SQL Server 分隔字符串函数实现

    在SQL Server中有时候也会遇到字符串进行分隔的需求.平时工作中常常遇到这样的需求,例如:人员数据表和人员爱好数据表,一条人员记录可以多多人员爱好记录,而往往人员和人员爱好在界面展示层要一并提交 ...

  5. SQL Server数据库ROW_NUMBER()函数使用详解

    SQL Server数据库ROW_NUMBER()函数使用详解 摘自:http://database.51cto.com/art/201108/283399.htm SQL Server数据库ROW_ ...

  6. SQL Server UDF用户自定义函数

    UDF的定义 和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且尅作为一个单元爱进行调用.UDF和存储过程的主要区别在于返回结果的方式. 使用UDF时可传入参数, ...

  7. SQL Server数据库PIVOT函数的使用详解(一)

    http://database.51cto.com/art/201108/285250.htm SQL Server数据库中,PIVOT在帮助中这样描述滴:可以使用 PIVOT 和UNPIVOT 关系 ...

  8. 10、SQL Server 内置函数、临时对象、流程控制

    SQL Server 内置函数 日期时间函数 --返回当前系统日期时间 select getdate() as [datetime],sysdatetime() as [datetime2] getd ...

  9. SQL Server 2005中的CHECKSUM功能

    原文:SQL Server 2005中的CHECKSUM功能 转自此处 页面 checksum 是SQL2005的新功能,提供了一种比残缺页检测强大的机制检测IO方面的损坏.以下是详细描述: 页面 C ...

随机推荐

  1. 3dsmax2020卸载/安装失败/如何彻底卸载清除干净3dsmax2020注册表和文件的方法

    3dsmax2020提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dsmax2020失败提示3dsmax2020安装未完成,某些产品无法安装,也有时候想重新 ...

  2. (转)Linux服务器SNMP常用OID

    原文:https://www.haiyun.me/archives/linux-snmp-oid.html 收集整理一些Linux下snmp常用的OID,用做服务器监控很不错.服务器负载: 1 2 3 ...

  3. 安装多个PHP环境会导致phpinfo和php -v中查看到的PHP版本不一致

    以前在上一个公司用的是集成环境wamp,PHP版本是5.5.后面换了一个公司,项目用的是PHP版本是5.2.今天想打开以前的项目想优化一下,发现pdo_mysql.dll扩展无法加载,于是想看看是不是 ...

  4. bootstrap table 以及xEdittable的应用

    以前一直没有用过  bootstrap  表格框架,因为项目css框架用的是bootstrap,为考虑到统一性的原因,所以选用了这个框架 步骤: 第一步:引用 <link href=" ...

  5. Dictionary<string, object>不区分大小写

    Dictionary<string, object> dic = new Dictionary<string, object>(StringComparer.OrdinalIg ...

  6. jsp继承rapid库

    如果jsp不使用继承方式开发,而是用标准的指令或动作元素去include,实在是太多重复代码. rapid-framework是谷歌的一个项目,可以实现jsp网页的继承,也就是书写模板页. 但是在ma ...

  7. [转] Entity Framework添加记录时获取自增ID值

    本文转自:http://blog.csdn.net/educast/article/details/8632806 与Entity Framework相伴的日子痛并快乐着.今天和大家分享一下一个快乐, ...

  8. Swift构造器链

    IDE:Xcode Version7.3.1 指定构造器: 1>名字为init的方法前没有前缀(子类重写时有override除外), 2>一个类中至少有一个指定构造器,其必须初始化类中的所 ...

  9. Expression Blend实例中文教程(8) - 动画设计快速入门StoryBoard

    上一篇,介绍了Silverlight动画设计基础知识,Silverlight动画是基于时间线的,对于动画的实现,其实也就是对对象属性的修改过程. 而Silverlight动画分类两种类型,From/T ...

  10. Java 线程--实现java.lang.Runnable接口实现线程

    Java线程的第一种实现方式,主要分两步,第一步是继承java.lang.Thread; 第二步是重写run()方法.接下来我们来看Java线程的第二种实现方式,也是分为两步,第一步,写一个类实现ja ...