今天特地查了一下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. UGUI Slider的onValueChanged事件

    在本文,你将学到如何将UGUI Slider的onValueChanged事件进行统一管理. using System; using UnityEngine; using UnityEngine.UI ...

  2. java 接口的学习

    1   什么是接口 接口是一种引用数据类型.使用interface声明接口,形式:  public interface 接口名称{} 1.1.1 接口的特性 [1] 接口中可以声明属性.接口中定义的所 ...

  3. spark第十篇:Spark与Kafka整合

    spark与kafka整合需要引入spark-streaming-kafka.jar,该jar根据kafka版本有2个分支,分别是spark-streaming-kafka-0-8和spark-str ...

  4. python3.6 for pygame安装

    首先下载好文件: pygame下载网址:http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame 找到pygame-1.9.2b8-cp36-cp36m-wi ...

  5. c++ 网络编程(三) LINUX/windows 进程间的通信原理与实现代码 基于多进程的服务端实现

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613027.html 锲子:进程与线程是什么,他们的区别在哪里: 1 进程概念 进程是程序的一 ...

  6. java里面如何提升编写速度

    一般情况下,编写程序,是在规定的时间内,并且在一段时间内很好的按成,那么就必须要套用现成的东西.在一个新的功能中,如何调用现成的东西呢,那么就是使用第三方包或者是使用自己总结的代码库.接来下是自己看到 ...

  7. 1.6 js基础

    必会示例: i的问题 qq头像完整版 this的错误用法 按住鼠标连续加减 封闭空间 甲乙的问题 京东轮播图 苏宁延迟选项卡 无限下拉菜单 淘宝短发送倒计时 1.必须会的         选项卡.按钮 ...

  8. 从C语言的整数取值范围说开去

    在ILP32中, char, short, int, long, long long, pointer分别占1, 2, 4, 4, 8, 4个字节,在 LP64中, char, short, int, ...

  9. Centos7 ftp服务器搭建

    1.使用yum安装ftp服务端: yum install -y vsftpd 2.使用yum安装ftp客户端: yum install -y ftp.x86_64 3.开启ftp服务设置开机启动并查看 ...

  10. Require.js 源码分析

    本文将简单介绍下个人对require.js的源码分析,简单分析实现原理 一.require加载资源的流程 require中,根据AMD(Asynchronous Module Definition)的 ...