今天特地查了一下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. JRebel idea 热部署

    下载链接:https://pan.baidu.com/s/1CUvEarKVARJF46LJ2W90Lg 提取码:s46w 下载完以后是个ZIP(jr-ide-intellij-7.1.5_13-17 ...

  2. Python练习 | Web本质Socket

    #--------------------------------客户端-------------------------------------- # 导入socket库 import socket ...

  3. PHP 字符串 操作符<<< 使用的注意事项

    在看<深入PHP和JQeury开发>过程中,遇到字符串 操作符<<<,代码没有问题,但格式却要求特别严格,找到PHP手册上的实例,翻译过来,留作后用. A string ...

  4. Python时间time模块介绍

    一.明确时间元组 二.测试代码#!/usr/bin/env python # -- coding: utf-8 --' """ 时间模块,time的相关操作与测试 &qu ...

  5. SpringBoot项目中获取applicationContext对象

    ApplicationContext 对象是Spring开源框架的上下文对象实例,也就是我们常说的Spring容器,一般情况下我们是不用手动来管理它,而是由Spring框架自己来维护bean之间的关系 ...

  6. [目录]ASP.NET web api开发实战

    第一章:Restful web service v.s. RPC style web service 第二章:ASP.NET web api v.s. WCF v.s. ASP.NET web ser ...

  7. 【ExtJS】关于Component生命周期

    很久以前就学习过extjs的组件生命周期,很久之后,再回头看一看,又增加好多新的认识. extjs组件生命周期大体分为3个阶段:初始化.渲染.销毁. 第一阶段:初始化 初始化工作开始于组件的诞生,所有 ...

  8. LoadRunner使用

    LoadRunner使用 软件版本:12.53 build 1203 操作系统: Windows7 以下内容摘录自LoadRunner的官方帮助文档. 介绍 LoadRunner现在是HP公司的产品, ...

  9. Game-Tech小游戏专场第二趴,这次帝都见

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云 发表于云+社区专栏 自从小游戏推出以来,凭借微信带来的巨大流量和变现能力,小游戏生态极速地建立了起来,短短半年多时间已经出 ...

  10. 利用git工具命令简单的从github上拷贝和上传代码

    第一:从github上拷贝项目到本地   1.在github上建立一个项目名为:MygitTest 2.在我们本地电脑上把这个项目拷贝下来:直接选择一个文件夹,右键选择git Bash here 直接 ...