落户云栖,专注数据库

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

既然转移到云栖,先来个Forwared 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)

)

go

 

insert into testtb default values

go 20

 

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

DBCC TRACEON(3604)

GO

DBCC IND(testpage,'testtb', 1)---find the data page

GO

DBCC PAGE('testpage', 1, 79, 3)-----view data page find slot 2(ID=3)

GO

 

 

现在我们来更新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

 

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

图中我省去了数据内容

code

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

GO


                             1-4

 

 

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

(此时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=3

 

DBCC 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 =0x4F00000001000200

 

DECLARE @HeapRid BINARY(8)

SET @HeapRid = 0x4F00000001000200

       SELECT

       CONVERT (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 on

 

select * from testtb where id=2

 

select * 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 10000

 

dbcc dropcleanbuffers

select * from testbp

 

SELECT 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 15MB

 

update dbo. testbp set str2=replicate('t', 1000)---make forwarded recordes

 

dbcc dropcleanbuffers

 

select * from testbp

 

 

SELECT 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_count

 from

    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)操作时应注意时间窗口

 

结语

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

 

 

目录
相关文章
|
1月前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
在9月20日2024云栖大会上,阿里云智能集团副总裁,数据库产品事业部负责人,ACM、CCF、IEEE会士(Fellow)李飞飞发表《从数据到智能:Data+AI驱动的云原生数据库》主题演讲。他表示,数据是生成式AI的核心资产,大模型时代的数据管理系统需具备多模处理和实时分析能力。阿里云瑶池将数据+AI全面融合,构建一站式多模数据管理平台,以数据驱动决策与创新,为用户提供像“搭积木”一样易用、好用、高可用的使用体验。
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
|
2月前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
阿里云瑶池在2024云栖大会上重磅发布由Data+AI驱动的多模数据管理平台DMS:OneMeta+OneOps,通过统一、开放、多模的元数据服务实现跨环境、跨引擎、跨实例的统一治理,可支持高达40+种数据源,实现自建、他云数据源的无缝对接,助力业务决策效率提升10倍。
|
3月前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
阿里云数据库重磅升级!元数据服务OneMeta + OneOps统一管理多模态数据
|
存储 人工智能 Cloud Native
2022云栖精选—2022云栖大会云原生数据库峰会 开场致辞
致辞嘉宾:李飞飞,阿里巴巴集团副总裁,阿里云数据库产品事业部负责人,ACM和IEEE会士(FELLOW)
2022云栖精选—2022云栖大会云原生数据库峰会 开场致辞
|
存储 SQL 人工智能
2022云栖精选—达摩院加持下的数据库技术前沿
汪晟 阿里巴巴集团资深技术专家 达摩院数据库与存储实验室系统与安全方向负责人
2022云栖精选—达摩院加持下的数据库技术前沿
|
存储 Cloud Native NoSQL
2022云栖精选—云时代数据库应用最佳实践
李圣陶 阿里云数据库资深解决方案专家
2022云栖精选—云时代数据库应用最佳实践
|
存储 弹性计算 资源调度
2022云栖精选—《Serverless数据库技术研究报告》 解读与发布
姜春宇 中国信通院云计算与大数据研究所主任
2022云栖精选—《Serverless数据库技术研究报告》 解读与发布
|
存储 Kubernetes Cloud Native
2022云栖精选—打造世界级云原生数据库开源社区
王远 阿里云数据库产品事业部资深技术专家 架构部负责人
2022云栖精选—打造世界级云原生数据库开源社区
|
数据采集 Kubernetes Cloud Native
|
存储 安全 数据管理
2022云栖精选—云时代的数据库技术趋势 跨域数据管理
杜小勇 中国人民大学明理书院院长 中国计算机学会理事 数据库专委会资深委员
2022云栖精选—云时代的数据库技术趋势 跨域数据管理