SQL Server ->> 校检函数CHECKSUM、CHECKSUM_AGG、BINARY_CHECKSUM和HASHBYTES
今天特地查了一下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
SQL Server ->> 校检函数CHECKSUM、CHECKSUM_AGG、BINARY_CHECKSUM和HASHBYTES的更多相关文章
- sql server中常用方法函数
SQL SERVER常用函数 1.DATEADD在向指定日期加上一段时间的基础上,返回新的 datetime 值. (1)语法: DATEADD ( datepart , number, date ) ...
- SQL Server 内置函数、临时对象、流程控制
SQL Server 内置函数 日期时间函数 --返回当前系统日期时间 select getdate() as [datetime],sysdatetime() as [datetime2] getd ...
- SQL Server:字符串函数
以下所有例子均Studnet表为例: 1. len():计算字符串长度 len()用来计算字符串的长度,每个中文汉字或英文字母都为一个长度 select sname, len(sname) from ...
- SQL Server 分隔字符串函数实现
在SQL Server中有时候也会遇到字符串进行分隔的需求.平时工作中常常遇到这样的需求,例如:人员数据表和人员爱好数据表,一条人员记录可以多多人员爱好记录,而往往人员和人员爱好在界面展示层要一并提交 ...
- SQL Server数据库ROW_NUMBER()函数使用详解
SQL Server数据库ROW_NUMBER()函数使用详解 摘自:http://database.51cto.com/art/201108/283399.htm SQL Server数据库ROW_ ...
- SQL Server UDF用户自定义函数
UDF的定义 和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且尅作为一个单元爱进行调用.UDF和存储过程的主要区别在于返回结果的方式. 使用UDF时可传入参数, ...
- SQL Server数据库PIVOT函数的使用详解(一)
http://database.51cto.com/art/201108/285250.htm SQL Server数据库中,PIVOT在帮助中这样描述滴:可以使用 PIVOT 和UNPIVOT 关系 ...
- 10、SQL Server 内置函数、临时对象、流程控制
SQL Server 内置函数 日期时间函数 --返回当前系统日期时间 select getdate() as [datetime],sysdatetime() as [datetime2] getd ...
- SQL Server 2005中的CHECKSUM功能
原文:SQL Server 2005中的CHECKSUM功能 转自此处 页面 checksum 是SQL2005的新功能,提供了一种比残缺页检测强大的机制检测IO方面的损坏.以下是详细描述: 页面 C ...
随机推荐
- Vue axios 上传图片
上传图片接口 // 上传图片 export const uploadBanner = formData => { return axios.request({ url: 'manage/slid ...
- SQLite3开发接口函数详解
SQLite3是SQLite一个全新的版本,它虽然是在SQLite 2.8.13的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和API. SQLite3是为了满足以下的需求而开发的: ...
- JS及Dom练习 | 页面滚动文字
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- (转)如何使用Journalctl查看并操作Systemd日志
原文:https://blog.csdn.net/zstack_org/article/details/56274966 内容简介 作为最具吸引力的优势,systemd拥有强大的处理与系统日志记录功能 ...
- LinuxShell脚本编程基础4-条件测试与条件判断
1.条件测试(test,[]) #! /bin/bash echo "请输入登陆的用户名:" read name1 if test "$name1" = &qu ...
- LINUX安装UNZIP
安装完linux ,发现没有UNZIP,没办法,重新安装. 1.获取unzip源码 sudo wget http://downloads.sourceforge.net/infozip/unzip55 ...
- 028-applicationContext.xml配置文件
版本一 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http: ...
- 通过反射获取及调用方法(Method)
1.获取方法使用反射获取某一个类中的方法,步骤:①找到获取方法所在类的字节码对象②找到需要被获取的方法 Class类中常用方法: public Method[] getMethods():获取包括自身 ...
- PHP的file_get_contents()方法,将整个文件读入字符串中
<?php $post_data = file_get_contents("e:\\1.txt"); echo $post_data; ?> 更多信息看这里:http: ...
- Hibernate 一对多自身关联(同一表中子父目录树形结构)