%%lockres%%和%%physloc%%

%%lockres%%和%%physloc%%


编辑:2011-10-18

可以将这两者看做是标量函数,不同行返回不同值。下面分别说明,测试环境如下:

if object_id('ta') is not null
  drop table ta
if object_id('tb') is not null
  drop table tb
go
create table ta(id int, col1 varchar(20))
create table tb(id int, col2 varchar(20))
create unique clustered index c1 on tb(id)
create nonclustered index nc1 on tb(col2)
go
insert into ta values(1, 'a')
insert into ta values(2, 'b')
insert into ta values(3, 'c')
go
insert into tb values(1, 'a')
insert into tb values(2, 'b')
insert into tb values(3, 'c')

Go

一.%%lockres%%  

出现在SQL SERVER 2005及以上版本中。

通过观察发现:只有叶节点(聚集索引和非聚集索引)和数据页(堆,无聚集索引)才需要加锁。非叶节点上是不进行加锁的(为什么?)。
如何表示键锁(KEY LOCK)所锁定的键呢?你最初的答案当然是键值了,但是索引的列数目不同,而且类型也不同,所以不太适合表示。SQL SERVER使用一种HASH算法,由键值生成一个6字节的字符串,由这6字节表示键锁所锁定的键。
通过实验发现:该算法应该仅仅跟索引键值有关。
我们可以通过%%lockres%%来查看该hash字符串。由于该字符串值和键值有关,所以通过不同索引查询,会使用不同的键值(叶节点中不同),于是同一数据行的%%lockres%%值也不尽相同。

select *, %%lockres%% from tb with (index=c1)
结果:
id          col2                 
----------- -------------------- --------------------------------
1           a                    (010086470766)
2           b                    (020068e8b274)
3           c                    (03000d8f0ecc)

select *, %%lockres%% from tb with (index=nc1)
结果:
id          col2                 
----------- -------------------- --------------------------------
1           a                    (62007a313325)
2           b                    (640044e42670)
3           c                    (660091aafaf5)

注意:当计划为堆扫描(即没有使用索引),%%lockres%%的值为RID,格式为 文件ID:页ID:行ID。
select *, %%lockres%% from ta
结果:
id          col1                 
----------- -------------------- --------------------------------
1           a                    1:77:0
2           b                    1:77:1
3           c                    1:77:2

二.%%physloc%%
 出现在SQL SERVER 2008及以上版本中。它指出数据行的物理地址,其格式为Binary(8),其中1~4字节为pageno(页ID),5~6字节为fileno(文件ID),7~8字节为slotno(行ID),和%%lockres%%不同的是,不管有无聚集索引,%%physloc%%都表示为行所在的物理地址,如果想要显示为常见的文件/数据页/行的格式可以使用下面的函数:
1)    可以使用sys.fn_physlocformatter函数将%%physloc%%转换成一个(file:page:slot)格式的字符串。
2)    如果需要将file/page/slot分别放在一列中,可以使用fn_PhysLocCracker函数。
select *, %%physloc%% as phy from ta
结果:
id          col1           phy
----------- -------------------- ------------------
1           a         0x5900000001000000
2           b         0x5900000001000100
3           c         0x5900000001000200

select *, %%physloc%% as phy from tb
结果:
id          col2           phy
----------- -------------------- ------------------
1           a         0x5D00000001000000
2           b         0x5D00000001000100
3           c         0x5D00000001000200

经过转换后:
select *, %%physloc%% as phy, sys.fn_physlocformatter(%%physloc%%) as phy1
from ta
结果:
id          col1            phy                phy1  
----------- -------------------   - ------------------        ----------
1           a           0x5900000001000000   (1:89:0)
2           b           0x5900000001000100   (1:89:1)
3           c           0x5900000001000200   (1:89:2)

select a.*, %%physloc%% as phy, b.*
from ta a
cross apply fn_PhysLocCracker(%%physloc%%) b
结果:
id      col1      phy                file_id     page_id     slot_id     
-------- ------------- ------------------         ----------- ----------- -----------
1       a         0x5900000001000000 1           89          0
2       b         0x5900000001000100 1           89          1
3       c         0x5900000001000200 1           89          2

三.参考文献
1.    Microsoft Sql server 2008 internals, p264,p626
2.    http://www.sqlskills.com/blogs/paul/post/SQL-Server-2008-New-%28undocumented%29-physical-row-locator-function.aspx
3.    http://sqlfool.com/2009/09/undocumented-function-in-sql-2008/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值