前言

上一节我们结束了Hash Match Aggregate和Stream Aggregate的讲解,本系列我们来讲讲关于SQL Server中的计算列问题,简短的内容,深入的理解,Always to review the basics。

初探计算列持久化(Compued Column Persisted)

在SQL Server 2005就引入了计算列,我们首先稍微看下在msdn关于计算列的定义:计算列由可以使用同一表中的其他列的表达式计算得来。表达式可以是非计算列的列名、常量、函数,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能为子查询。实际上就是为了定义一个列来对其他列来进行计算可以是列名、函数等,那么它的使用场景是什么呢?下面我们首先来举个例子。当需要导出一些值时,此时这些值需要通过计算才能被导出,同时呢,有一些列还依赖于另外的一列或者更多列,如果一个列进行了更新则其依赖的列必须同步进行更新,上述场景通过对一个列或者多个列进行计算,此时我们需要定义一个将一个列或者多个列进行计算得到的值的列,这就是计算列。我们来看一个典型的例子,在一个公司上班的所有员工,在公司内部系统中会存其所有员工的信息,比如员工编号、出生日期等,如果此时我们需要导出员工的退休日期呢,假设在中国现在男性退休时间为60年后,此时我们需要通过出生日期算出60年后的日期,也就说在表中还需要定义一个退休日期列。下面我们创建表来看看计算列。

USE TSQL2012
GO CREATE TABLE Employee
(
employeeNumber INT NOT NULL, --员工编号
employeeBirth DATETIME NOT NULL, --出生日期
employeeRetirement AS (DATEADD(YEAR, , (employeeBirth)-())) PERSISTED --退休日期
)

此时我们看到表中关于退休日期的设计,显示其已经是持久化了的

接下来我们插入测试数据看看

USE TSQL2012
GO INSERT INTO dbo.Employee( employeeNumber, employeeBirth )
SELECT ,'1985-12-13' UNION ALL
SELECT ,'1989-11-18' UNION ALL
SELECT ,'1990-01-19' UNION ALL
SELECT ,'1993-06-13' UNION ALL
SELECT ,'1995-07-23'

然后我们来查询表

USE TSQL2012
GO SELECT *
FROM dbo.Employee

此时我们通过查询雇员表得到其每个雇员的退休日期,到这里是没什么问题的,既然我们设置它是持久化的,也就说当其他列发生改变时计算列也会对应发生改变,突然有一天编号为305423的雇员和录入信息的同事交流,他其实是1986年出生的,上面的1985年是身份证上的,身份证搞错了,此时我们需要更新其出生日期到1986年,如下

UPDATE dbo.Employee SET employeeBirth = '1986-12-13' WHERE employeeNumber = ''

接下来我们再来查询数据看看。

此时我们发现当出生日期发生修改时,其对应的计算列也进行了同步由原来的2045更新到了2046,上述我们添加在计算列中添加了Persisted关键字,是不是因为添加这个关键字导致持久化从而当一个列进行更新时,计算列也就同步更新了呢,难道这就是Persisted持久化的作用吗,实际情况不是这样的,当你去掉Persisted关键字此时也会进行同步更新(不信你可以试试),那么Persisted关键字的作用是什么呢?事实情况是这样的,当我们在列上创建了计算列时,此时计算出来的数据并没有存在列中(至于存在哪里我也不知道),计算的数据是在运行时计算出来的,当用Persisted关键字标识计算列之后,这个时候才是将计算结果存在表中计算列上。继续往下看数据存储空间使用情况就可以得到验证。

通过计算列持久化进一步探讨数据存储空间

下面我们来看看当未添加计算列、添加计算列、计算列持久化时表数据存储空间情况。下面我们来创建测试表

USE TSQL2012
GO CREATE TABLE [dbo].[ComputeColumn]
(
ID INT,
FirstName VARCHAR(),
LastName VARCHAR()
)
GO

在表中插入10万条数据

INSERT INTO [ComputeColumn] (ID,FirstName,LastName)
SELECT TOP ROW_NUMBER() OVER (ORDER BY a.name) RowID,
'Bob',
CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)% = THEN 'Smith'
ELSE 'Brown' END
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
GO

此时我们来看看有关表存储空间使用情况

USE TSQL2012
GO sp_spaceused '[ComputeColumn]'
GO

上述我们得知存储数据为2680KB,下面我们再来创建计算列看看。

ALTER TABLE dbo.[ComputeColumn] ADD
FullName AS (FirstName+' '+LastName)
GO

从这里我们可以得出当创建计算列时其数据根本没有存在列上,我们再来看看添加持久化关键字时情况又是怎样的呢

ALTER TABLE dbo.[ComputeColumn] ADD
FullName_P AS (FirstName+' '+LastName) PERSISTED
GO

当添加持久化关键字时此时表存储数据空间变为了4784KB,到此验证了当未添加Persisted关键字时,在计算列上的数据根本没有存在列上而是在运行时进行了计算,当用Persisted关键字标识计算列时此时数据才存在列上。

通过计算列持久化深入探讨数据存储空间

我们知道如果对列创建索引的话肯定需要一定空间来存储索引,上述我们对列进行了持久化,此时会增加表存储空间,要是我们创建索引是不是会增加表数据存储空间大小呢?我们在未创建计算列前先创建索引看看其表中各种数据空间存储大小,即在创建的列FullName上创建索引。

USE TSQL2012
GO CREATE NONCLUSTERED INDEX idx_comCol_FullName
ON dbo.ComputeColumn (FullName)

因为创建了索引,所以只是导致索引空间变大了,下面我们再创建计算列持久化并看看其表空间使用情况

USE TSQL2012
GO ALTER TABLE dbo.ComputeColumn ADD
FullName_P AS (FirstName+' '+LastName) PERSISTED

从上我们可以看到增加索引未导致表数据大小的增加,而创建计算列持久化则需要额外的空间。分析到这里为止,我们来给出一个基本结论:

计算列分析结论:计算列的用途主要用于多个计算并且比较复杂的计算,如果对计算列进行持久化虽然能够大大减少计算开销但是它会额外增加磁盘空间。

总结

本节我们学习了计算列以及将其持久化的基础内容,下一节我们讲讲关于计算列以及计算列持久化的性能问题,简短的内容,深入的理解,我们下节再会。

SQL Server-聚焦计算列持久化(二十一)的更多相关文章

  1. SQL Server-聚焦计算列或计算列持久化查询性能(二十二)

    前言 上一节我们详细讲解了计算列以及计算列持久化的问题,本节我们依然如前面讲解来看看二者查询性能问题,简短的内容,深入的理解,Always to review the basics. 持久化计算列比非 ...

  2. SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础

    原文:SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础 在前一篇博文中我们学习到了一些关于地理信息的基础知识,也学习了空间参照系统,既地球椭球体.基准.本初 ...

  3. SQL SERVER FOR 多列字符串连接 XML PATH 及 STUFF

    原文:SQL SERVER FOR 多列字符串连接 XML PATH 及 STUFF 本来用 Writer 写一篇关于一列多行合并的博客来的,结果快写完了时候,在一个插入代码时候,崩了,重新打开,居然 ...

  4. SQL Server 2014 聚集列存储

    SQL Server 自2012以来引入了列存储的概念,至今2016对列存储的支持已经是非常友好了.由于我这边线上环境主要是2014,所以本文是以2014为基础的SQL Server 的列存储的介绍. ...

  5. SQL Server分区键列必须是主键一部分

    SQL Server分区键列必须是主键一部分. 必须把分区列包含在主键/唯一约束/唯一索引的键列中. USE tempdb GO -- 测试表 CREATE TABLE dbo.tb( id int, ...

  6. SQL Server修改标识列方法(备忘)

    原文:SQL Server修改标识列方法(备忘) SQL Server修改标识列方法 ----允许对系统表进行更新 exec sp_configure 'allow updates',1 reconf ...

  7. sql server 自增列,值突然增大1000的情况

    sql server 自增列,值突然增大1000的情况   解决方法: 1 打开配置管理器2左面点击sql服务3右面 右键点击SQL Server(MSSQLSERVER) 4点击 启动参数5 在参数 ...

  8. sql server 某一列求和

    sql server 某一列求和 SELECT 患者来源,设备类型,检查部位,设备名称,convert(char(10),STUDY_DATE,121) as 日期, count(distinct 就 ...

  9. SQL Server 性能优化实战系列(二)

    SQL Server datetime数据类型设计.优化误区 一.场景 在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你 ...

随机推荐

  1. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  2. iOS可视化动态绘制连通图

    上篇博客<iOS可视化动态绘制八种排序过程>可视化了一下一些排序的过程,本篇博客就来聊聊图的东西.在之前的博客中详细的讲过图的相关内容,比如<图的物理存储结构与深搜.广搜>.当 ...

  3. Sublime Text3安装JsHint

    介绍 Sublime Text3使用jshint依赖Nodejs,SublimeLinter和Sublimelinter-jshint. NodeJs的安装省略. 安装SublimeLinter Su ...

  4. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

  5. DailyTick 开发实录 —— 开始

    2009 年我读了李笑来老师的<把时间当朋友>,知识了柳比歇夫的时间记录法.当时激动坏了,马上动手实践起来.一开始的时候,是用一个小本子,走到哪儿都带着.完成一件事,就记录一下花费的时间. ...

  6. 几个有趣的WEB设备API(二)

    浏览器和设备之间还有很多有趣的接口, 1.屏幕朝向接口 浏览器有两种方法来监听屏幕朝向,看是横屏还是竖屏. (1)使用css媒体查询的方法 /* 竖屏 */ @media screen and (or ...

  7. 深入浅出Redis-redis底层数据结构(上)

    1.概述 相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-valu ...

  8. SQLServer执行命令出现“目录无效的提示”

    异常处理汇总-数据库系列  http://www.cnblogs.com/dunitian/p/4522990.html 一般都是清理垃圾清理过头了,把不该删的目录删了 网上说法: 问题描述: 1.s ...

  9. X86和X86_64和X64有什么区别?

    x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...

  10. javascript数组查重方法总结

    文章参考地址:http://blog.csdn.net/chengxuyuan20100425/article/details/8497277 题目 对下列数组去重: var arr = ['aa', ...