SQL Server 存储引擎-剖析Forwarded Records

我们都知道数据在存储引擎中是以页的形式组织的,但数据页在不同的组织形式中其中对应的数据行存储是不尽相同的,这里通过实例为大家介绍下堆表的中特有的一种情形Forwared Records及处理方式.

概念

堆表中,当对其中的记录进行更新时,如果当前数据页无法满足更新行的容量,此时这行记录将会转移到新的数据页中,而原数据页中将会留下指针(文件号,页号,槽号)链接到新的数据页中.

Code 创建测试数据

create database testpage
go
use testpage
go
create table testtb
(
id int identity(1,1),
str1 char(100) default replicate('a',100),
str2 varchar(2000) default replicate('b',500),
str3 varchar(2000) default replicate('c',1000)
)
goinsert into testtb default values
go 20

Code 查看相关数据页 如图1-1

DBCC TRACEON(3604)GODBCC IND(testpage,'testtb', 1)---find the data pageGODBCC PAGE('testpage', 1, 79, 3)-----view data page find slot 2(ID=3)GO

                                  

                                                              图1-1

现在我们来更新ID=3的数据使当前数据页(79)无法容纳此行数据,然后观察数据页,

Code

update dbo.testtb set str2=replicate('t', 1000) where ID=3--update ID=3

GO

DBCC PAGE('testpage', 1, 79, 3)

GO

继续找到slot 2槽位(ID=3)观察 如图1-2所示,此时slot2数据的Record Type = FORWARDING_STUB,也就是此时槽位2只留下RID记录,数据转到其他数据页中了(Forwarding to  =  file 1 page 94 slot 0  )

 

                                                图1-2

 

这里稍微深入的讲下RID的存储内容,实例中根据dbcc page已经给我们展示RID的内容,实际上存储是16进制的如图1-2中的黑色部分(045e0000 00010000 00

).具体对应RID内容如图1-3

 

                                            图1-3

 

我们在找到实际存储ID=3的数据页看下数据内容(1:94:0) 如图1-4

图中我省去了数据内容

code

DBCC PAGE('testpage', 1, 94, 3)

GO

                                         图1-4

 

接下来我们继续更新ID=3让新的数据页也无法容纳它,然后观察相应的数据页如图1-5(三个dbcc page 合成图)

(此时ID=3的原始页94,槽号2指向了新的数据页位置184)如图所示1-5所示

code

insert into testtb default values
go 20----先插入一些数据update dbo. Testtb set str2=replicate('t', 2000),str3=replicate('t', 2000) where ID=3 GO---继续更新ID=3DBCC PAGE('testpage', 1, 79, 3)--------源ID=3,现在执行(1:184:2)
GO
DBCC PAGE('testpage', 1, 94, 3)--------第一次修改时ID=3存储位置(1:94:0),现在slot 0没有了
GO
DBCC PAGE('testpage', 1, 184, 3)------目前id=3的数据存储位置
GO

 

                                               图1-5

 

可以看出id=3的原始页(1:79:2)的数据再次变更后的由(1:94:0)挪到了(1:184:2)中,

而页号94槽号0就不存在了.

堆表中的非聚集索引.

当堆表中有非聚集索引存在时,非聚集索引RID指向的原始页位置

我们通过实例看下

注:关于heap rid我就不做详细介绍了,实例中通过查询转换可以算出10进制对应的RID

Code

CREATE UNIQUE NONCLUSTERED INDEX inx_1 ON testtb (id )DBCC IND(testpage,'testtb', -1)----find the index page (page type 2)115
GO
DBCC PAGE('testpage', 1, 115, 3)---find the heap rid where id=3 heap rid =0x4F00000001000200DECLARE @HeapRid BINARY(8)
SET @HeapRid = 0x4F00000001000200SELECTCONVERT (VARCHAR(5),CONVERT(INT, SUBSTRING(@HeapRid, 6, 1)+ SUBSTRING(@HeapRid, 5, 1)))+ ':'+ CONVERT(VARCHAR(10),CONVERT(INT, SUBSTRING(@HeapRid, 4, 1)+ SUBSTRING(@HeapRid, 3, 1)+ SUBSTRING(@HeapRid, 2, 1)+ SUBSTRING(@HeapRid, 1, 1)))+ ':'+ CONVERT(VARCHAR(5),CONVERT(INT, SUBSTRING(@HeapRid, 8, 1)+ SUBSTRING(@HeapRid, 7, 1)))AS 'Fileid:Pageid:slot'

可以看到select 的输出正好是(1:79:2)我们原始的id=3的位置

 

关于性能

由于forwarded record的存在,当访问到这种数据行时,会消耗额外的随机IO,从而影响性能.更有甚者,由于额外的数据页被放入内存中,造成BP的污染,致使性能下降.

(研发要求对一个频繁访问的大堆表更新扩充栏位,执行完了性能依旧下降有木有?)

 

我们通过简单实例来看下

访问forwarded record会造成额外IO如图2-1

Code

set statistics io onselect * from testtb where id=2select * from testtb where id=3

                                    图2-1

当表数据量大时,大批量更新扩充栏位会造成对缓冲池的污染

code

create table testbp
(
id int identity(1,1),
str1 char(100) default replicate('a',100),
str2 varchar(2000) default replicate('b',500),
str3 varchar(2000) default replicate('c',1000)
)
go
insert into testbp default values
go 10000dbcc dropcleanbuffers
select * from testbpSELECT count(*)*8/1024 AS 'Cached Size (MB)'
,CASE database_id
WHEN 32767 THEN 'ResourceDb'
ELSE db_name(database_id)
END AS 'Database'
FROM sys.dm_os_buffer_descriptors with(nolock)
where db_name(database_id)='testpage'
GROUP BY db_name(database_id) ,database_id
-----buffer pool 15MBupdate dbo. testbp set str2=replicate('t', 1000)---make forwarded recordesdbcc dropcleanbuffersselect * from testbpSELECT count(*)*8/1024 AS 'Cached Size (MB)'
,CASE database_id
WHEN 32767 THEN 'ResourceDb'
ELSE db_name(database_id)
END AS 'Database'
FROM sys.dm_os_buffer_descriptors with(nolock)
where db_name(database_id)='testpage'
GROUP BY db_name(database_id) ,database_id
------31MB

顺序执行代码时可以看出,testpage表更改前后占Buffer Pool的大小分别为15M,31M,对BP影响明显.

监控/发现

实际生产环境中我们需要监控一些性能指标用来辅助DBA解决问题,保证运维效率,针对这里,我们监控性能计数器中SQL Server Access Methods对象中的forwarded records/sec,如果你设定的了性能Baseline,这个值如果有异常变化,则需要我们关注.

同时我们也可以根据系统的DMF找出特定对象的forwarded records信息.代码如下

select object_name(object_id) as objectName,index_type_desc,forwarded_record_countfrom sys.dm_db_index_physical_stats(db_id(),null,null,null, 'detailed')where object_name(object_id)='testbp'
------view the forwarded records info

注:可以通过简单的Batch检索整个库甚至实例中的堆表的相关信息,有兴趣的朋友自己写下.

处理

如果发现了因为forwarded Recordes引起的性能问题,我们可以选择表中创建聚集索引改变数据组织结构(forwarded Recordes只在堆表中存在).如果无法添加聚集索引,也可以选择重组堆表(alter table heap rebuild)操作时应注意时间窗口

结语

任何事物都存在因果,套用数据库系统中,我们应该清楚自己的所作所为,以及带来的效用/影响.合理到位的分析,评估会让我们的工作变得从容.

转载于:https://www.cnblogs.com/shanksgao/p/4045917.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

u3d游戏开发视频潭州_游戏美术行业的发展与应用人工智能学院专业介绍及未来前景系列报告会二...

为了让2020级新同学对动漫专业加深认识,更好的规划学习,学院于11月12日6点晚邀请了校企合作单位“369云遮月游戏公司”在长安校区图书馆阶梯教室进行了游戏美术行业的发展与应用的报告会,主题围绕“专业介绍与发展前景”展开,云遮…

华为谷歌互利合作曝光:或将推Nexus手表

业内传言称,中国的华为科技公司和韩国LG电子公司,今年将为谷歌公司设计两款Nexus品牌的智能手机,这也将是华为科技第一次参加谷歌的Nexus硬件计划。日前,国外权威媒体披露了华为Nexus硬件计划的更多内容。除了一款5.7英寸的智能手…

unity2d随机生成物体_2020 年最好用的一键生成设计神器,全在这里了!

对于很多新手设计师来说,要高效率地完成一件看上去还不错的设计作品,其实并不是一件容易的事。特别是在现实的工作中,对于临危受命的任务,更是很少有人会耐心地等你慢慢去摸索的.……不慌,今天就掏出一份私藏已久的设计…

android MPV架构快速实现,不是所有的MPV都叫GL8,一体化智能座舱体验来袭

进入车内,首先映入眼帘的就是双12.3吋全液晶仪表及中控联屏,出色的画面质感在第一时间吸引了我的注意。当然,全新的一体化智能座舱理念,多屏互联、多维交互也是它的最大亮点之一。全新一代别克GL8家族采用迭代更新的通讯解决方案&…

基于SuperSocket的IIS主动推送消息给android客户端

在上一篇文章《基于mina框架的GPS设备与服务器之间的交互》中,提到之前一直使用superwebsocket框架做为IIS和APP通信的媒介,经常出现无法通信的问题,必须一天几次的手动回收程序池,甚至重起服务器,通常周末接到一个陌生…

明细表如何添加重量_关于Revit中明细表标准的导出及导入

Revit中明细表的作用非常大,项目中的数据归类整理及统计都离不开它,今天给大家分享一下如何在Revit中进行明细表标准的导出及导入,减少在实际项目中的重复性工作。1. 首先在Revit中新建一个项目文件,在平面视图中随便画几条管道&a…

鸿蒙还是不是安卓,华为捐赠鸿蒙核心架构!是否形成“三足鼎立”?

发布会已经开完,万物互联时代也已开启。经过测试,鸿蒙系统支持几乎所有的安卓软件,换句话说安卓用户可以无缝过渡到鸿蒙系统,相比安卓,速度更快,耗电量更低,这无疑比安卓系统的体验好出一个档次…

Filter基金会

一个、总结 简单的说,Filter的作用就是拦截(Tomcat的)service(Request,Response)方法。拿到Request、Response对象进行处理。然后释放控制。继续自己主动流转。其运用的还是“分层”的思想。至于为什么要增加这一层,为…

python2处理耗时任务_RabbitMQ Go客户端教程2——任务队列/工作队列

本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第二篇——任务队列。这些教程涵盖了使用RabbitMQ创建消息传递应用程序的基础知识。 你需要安装RabbitMQ服务器才能完…

使用 CSS3 伪元素实现立体的照片堆叠效

CSS3 里引入的伪元素让 Web 开发人员能够在不需要额外添加 HTML 标签的情况下制作出复杂的视觉效果。例如,:before 和 :after 这个两个 CSS3 伪元素就可以帮助你实现很多有趣的效果。本教程将告诉你如何使用 CSS3 为元素创建一组漂亮的图片堆叠效果。 效果演示 …

启发式搜索A*算法

A* 寻路算法 (2011-02-15 10:53:11) 转载▼标签: 游戏 分类: 算法概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的。 搜索区域(The Search Area) 我们假设某人要从 A 点移动到 B 点&#xff0c…

centos7全盘备份到本地_CentOS7下制作openssl1.1.1i RPM包并升级

点击上方"walkingcloud"关注,并选择"星标"公众号CentOS7下制作openssl1.1.1i RPM包并升级OpenSSL最新漏洞 OpenSSL官方发布了拒绝服务漏洞风险通告,漏洞编号为CVE-2020-1971漏洞详情OpenSSL是一个开放源代码的软件库包,应…

计算机网络基础专业找工作,2021计算机网络技术前景怎么样? 好找工作吗

很多同学想知道计算机网络技术前景怎么样,以下是一些相关信息的整理,希望能对同学们有所帮助!计算机网络技术前景从目前的情况看,企业的IT技术管理岗位一般设置为企业信息主管、总监等;工程技术岗位设置为网络工程师、…

安装 VMware Tools

第一步:挂载VMware Tools 第二步: 将上图VMware Tools-9.2.0 XXXX.tar.gz 复制到tmp目录(其他目录也行,没有权限操作需要 chmod 777 XXX 修改来获取权限) 第三步:解压 tar xvzf VMwareTools-9.2.0-799703.t…

LINUX添加一块网卡地址配置及问题

如何如何网卡服务重启慢关掉service NetworkManager stopchkconfig NetworkManager off 关于NetworkManager外链:http://www.linuxidc.com/Linux/2013-08/88809.htm 查看cat /etc/udev/rules.d/70-persistent-net.rules是否网卡名有重复VMware虚拟机安装好CentOS6.…

[每日一题jQuery] jQuery选择器总结:进一步过滤、同级操作、后代操作

jQuery选择器继承自CSS的风格,可以通过jQuery选择器找出特定的DOM元素,在此基础上对该元素做相应处理。jQuery不仅支持简单的标签选择器、类选择器、id选择器,还针对表单状态、子元素、元素顺序提供相应的选择器。如果熟练运用,则…

计算机桌面备份在哪里,电脑备份文件在哪里

电脑是我们经常使用的工具,为了放在电脑出现系统问题,有的朋友会将电脑系统备份,但是不知道电脑备份文件放在什么地方了,电脑备份文件在哪里呢?很多朋友还是不知道的,所以针对电脑备份文件保存在哪里的问题…

如何用python打印田字格_如何用 3D 打印一双顶级跑鞋回形针

马拉松赛场上的跑鞋五光十色,除了美观之外,它们还有一个重要作用:保护运动员不受伤害。跑步时,从脚碰到地面开始会受到地面的反作用力。从着陆的减速到随着脚步推蹬过程的加速,这一过程中脚和地面的压力会达到两个峰值…

什么可以作为gcroot_面包果既能当水果又可以作为粮食,国内却无法普及,这是为什么?...

水果是我们大多数人日常都会吃的一种食物,现在国内的水果种类也是非常多,不管是国内本有的还是从国外进口的。但是你吃过面包果吗?可千万不要把它和非洲大陆上的面包树混为一谈,面包果和它半毛钱关系没有,它的原产地在…

cookies的存值问题

2019独角兽企业重金招聘Python工程师标准>>> cookies存值问题,项目中遇到问题初始化时由于cookies中存在冒号导致存到cookies中时取出来被转码了,冒号的转码从cookies中取出来为%A3 ,当然一开始我的设想是保存到cookies换一种保存…