浅析SQL Server数据库中的伪列以及伪列的含义
原文:浅析SQL Server数据库中的伪列以及伪列的含义

本文出处:http://www.cnblogs.com/wy123/p/6833116.html

SQL Server中的伪列

下午看QQ群有人在讨论(非聚集)索引的存储,
说,对于聚集索引表,非聚集索引存储的是索引键值+聚集索引键值;对于非聚集索引表,索引存储的是索引键值+RowId,这应该是一个常识,对此不作具体详细阐述。
这里主要是提到的RowId引起了一点思考。
那么,这个RowId是个什么玩意?能不能更加直观一点来看看RowId的信息?代表什么含义?这个当然也是可以的。
Oracle中的表中有一个伪列的概念,就是在查询表的时候加上select rowid,* from Table,会查询出来伪列。
SQL Server中同样有这么一个伪列,在SQL Server中,这个伪列可以认为是数据行的物理地址,下面简单来观察一下这个RowId以及RowId的含义。

伪列的测试

  建一张简单的表,下面借助这个表来查看说明伪列

CREATE TABLE Test
(id int identity(1,1),name varchar(50)
)
GOINSERT INTO Test VALUES (NEWID())
GO 100

SQL Server中有一个未公开的伪列“%%physloc%%”,也就是在查询的时候,对于任何一张表,可以加上这个字段,比如如下,就可以查到表中每一行的伪列。

这个伪列的类型是binary(8),也就是有8个字节,参考上图的DATALENGTH(%%physloc%%) as Len,
%%physloc%%返回的记录的物理地址,其中前四个字节表示页号,中间两个字节表示文件号,最后两个字节表示槽号
为了更加方便地观察伪列的含义,sqlserver提供了一个未公开的系统函数sys.fn_PhysLocFormatter,下面借助sys.fn_PhysLocFormatter这个函数来继续观察这个伪列
如下图,这里就可以清晰地看到伪列中的信息了。

  比如第一行中的(1:73:0),上面说了,其中前四个字节表示页号,中间两个字节表示文件号,最后两个字节表示槽号,
  (1:73:0)这种格式是经过sys.fn_PhysLocFormatter格式化显式之后的结果。
  把文件号1放在最前面,中间的73是页号(page number),最后一位0是槽号(sloc number)。
  下面粗略地说一下这几个字段的含义。这里要求对SQL Server的存储只是有一个基本的认识,否则看的云里雾里。

  1,首先说什么是文件号

  如截图,文件号就是数据库的数据文件编号,这里只有一个数据文件,文件编号为1,
  建表的时候默认(这里也只能建立)建立在fileid = 1 的文件上面,fileid=2的是日志文件,就不多说了。

  2,其次是页号,页号就是分配给当前这张表的数据页面(8kb的最小分配单元)的页号,我们看一下Test这个表的页面情况

  借助DBCC IND命令,查询分配给这个表的页面信息,其中77号页面是IMA也面,至于什么事IMA页面,不多解释。
  73号页面才是真正存储数据的页,与上面的1:73:0中的73一样,没毛病。

  

  3,最后看一下槽号,槽号的概念要对SQL Server的数据页面有一个基本的认识,这里盗用一张网友的图。

  所谓的槽号就是在数据页面中,每个页面存储多行数据,槽号用来标记每一行数据的偏移量,用大白话说就是“存储每一行数据的地址空间开始的位置”,
  因为每一行数据的总长度是不一样的(存在可变长度列的情况下),每一行的占用的存储空间也是不一样的,
  槽号或者行偏移量就是说明每一行数据在页内的开始位置。
  不过sys.fn_PhysLocFormatter格式化显式的槽号并不是如下截图的偏移量,而是第N个数据行的这个N的信息,
  因此第1行的槽号就是1,第2行的槽号就是2,以此类推,当第一个page存储满之后,从第二个page开始存储,槽号又从0开始编号且累加

  

  

  至此,对SQL Server的伪列,也就说经常说的RowId有了一个简单的认识。
  这里可以认为,在SQL Server数据库中,伪列RowId就是数据行的物理地址,至于别的数据库中的伪列(RowId)是不是物理地址倒是不确定(很有可能也是的)

这里简单提一下一开始说的一个问题:
为什么SQL Server的聚集表(有聚集索引的表)存储数据的时候存储的是“索引键值+聚集索引键值”,对于非聚集索引表,索引存储的是索引键值+RowId?
或者反过来说,为什么聚集索引表的非聚集索引存储的是“索引键值+聚集索引键值”而不是“索引存储的是索引键值+RowId”
作为一个常识,聚集索引要按照聚集索引的顺序存放,这就意味着聚集索引表的行数据物理位置有可能发生变化,比如在众所周知的“页拆分(page split)”中发生变化,
在数据行的物理位置发生了变化的时候,如果非聚集索引存储的是索引键值+RowId,那么这个RowId也势必要发生变化,这个变化当然要耗费一定的性能,
为了防止此种情况的发生,聚集表中的非聚集索引存储成相对不变的索引键值+聚集索引键值,因为在数据行的物理位置发生变化的时候,聚集索引键值是相对不变的,这一点也不难理解。
当然有一种例外,当对聚集索引表做更新的时候,直接更新聚集索引的键值,这样的话,也有可能造成聚集索引表中当前数据行的物理位置发生变化,这一点也比较有意思,就不展开叙述了。
这一点跟绕口令一样,这里要求对SQL Server中的聚集索引和非聚集索引,以及存储结构有一个基础的认识才容易理解。

最后高能预警

  高能预警,别说我瞎比比误导人,上述解析伪列的函数sys.fn_PhysLocFormatter是一个未公开的函数,
  未公开的函数就有可能潜在一些问题,事实上这个函数有一个非常严重的bug。
  该bug就是在解析物理存储位置的时候有一定的逻辑错误,这个问题早有细心的人分析过了
  参考:http://blog.itpub.net/81227/viewspace-751898/
  目前测试来看,在SQL Server 2014中仍然存在bug,N前年啃书的时候就了解到有这么一个函数,
  但是一直不想提及sys.fn_PhysLocFormatter这个函数的原因,因此对于未公开的函数,请不要做验证性测试,
  再次声明:该函数有bug,请谨慎使用。

  附上这个函数的源代码,并参考原文的结论

create function sys.fn_PhysLocFormatter (@physical_locator binary (8))returns varchar (128)
asbegindeclare @page_id binary (4)declare @file_id binary (2)declare @slot_id binary (2)-- Page ID is the first four bytes, then 2 bytes of page ID, then 2 bytes of slot--
     select @page_id = convert (binary (4), reverse (substring (@physical_locator, 1, 4)))select @file_id = convert (binary (2), reverse (substring (@physical_locator, 5, 2)))select @slot_id = convert (binary (2), reverse (substring (@physical_locator, 7, 2)))return '(' + cast (cast (@file_id as int) as varchar) + ':'+       cast (cast (@page_id as int) as varchar) + ':'+       cast (cast (@slot_id as int) as varchar) + ')'end

  问题出在reverse函数上。
  reverse函数的作用是字符反转,而不是字节反转,当遇到81-FE之间的字节时,被认为是双字节字符而组合在一起参与反转操作,造成了错误。

总结

  本文简单阐述了SQL Server中的伪列,以及伪列的含义,通过伪列对非聚集索引以及数据行的存储结构有一个简单的了解。

posted on 2017-09-11 09:18 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/7503405.html

浅析SQL Server数据库中的伪列以及伪列的含义相关推荐

  1. SQL Server数据库中使用sql脚本删除指定表的列

    在SQL Server数据库中删除某一列,使用数据库管理工具直接可视化操作是很简单的,但是如果要用sql脚本呢?可能你会说很简单,直接用 ALTER TABLE [要删除的字段所在的表名] DROP ...

  2. SQL Server数据库中、获得刚插入新记录的自动ID号

    以下的文章主要是介绍在SQL Server数据库中正确获得刚插入一条新记录的自动ID号的实际操作过程,下面就是文章对其的主要内容的具体描述,望大家在浏览之后会对其有更深的了解. 使用[IDENT_CU ...

  3. 通过VB向SQL Server数据库中录入数据

    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 一.数据录入 通过VB向SQL Se ...

  4. 如何对两个大型SQL Server数据库中的数据进行快速估计比较,以查看它们是否相等

    Bringing impactful analysis into a data always comes with challenges. In many cases, we rely on auto ...

  5. SQL Server数据库中的T-SQL如果存在语句概述

    This article walks through different versions of the T-SQL IF EXISTS statement for the SQL database ...

  6. SQL server数据库中双引号(英文)的使用

    SQL server数据库中,一般我们用单引号将字符串等括起来使用,从而用来标识一个字符串.那么我们在什么时候使用双引号呢. 双引号在数据库中是用来标识一个事物名字的,例如:表的名字,约束的名字,列的 ...

  7. 在ASP.NET中将图片存储到Sql Server数据库中

    在ASP.NET中将图片存储到Sql Server数据库中 http://hi.baidu.com/rayshow/blog/item/360e8ff9662c8b5a252df268.html 索引 ...

  8. 清空SQL Server数据库中所有表数据的方法(转)

    清空SQL Server数据库中所有表数据的方法 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可能陷入 ...

  9. mysql raiserror_RAISERROR在SQL Server数据库中的用法

    raiserror  是由单词 raise error 组成 raise  增加; 提高; 提升 raiserror 的作用: raiserror 是用于抛出一个错误.[ 以下资料来源于sql ser ...

最新文章

  1. 数据恢复工具PhotoRec
  2. 大多数日志文件的后缀名是_编程小短文:find,让你随心所欲查找整块磁盘的任意文件...
  3. 2022-02-25
  4. IOS - IPhone或IPAD,如何恢复出厂操作系统?
  5. 在计算机硬件中mo是指,计算机导论 - [课件]第2章 计算机系统的硬件.ppt
  6. linux学习笔记1:基础知识
  7. 【英语学习】【WOTD】commemorate 释义/词源/示例
  8. SQL Server中的基数估计过程
  9. ajax请求,返回值为304 Not Modified 错误原因与解决办法
  10. Pytorch专题实战——数据转换(Dataset Transforms)
  11. 专访车音网创始人沈康麒:语音识别有无数个痛点
  12. 云顶之弈机器人法爆_云顶之弈法爆流斗法阵容详解
  13. [Jscript]Js导出Excel
  14. 10款开源网上教学课程管理系统
  15. Kubelet cAdvisor 资源监控
  16. mycat连接数据库8.0以上 处理程序连接query_cache_size报错信息 mycat升级数据库踩坑
  17. 走近求伯君1 求伯君,1964年11月26日出生于浙江新昌县。
  18. 【风控体系】现金贷业务的风控体系
  19. 信息爆炸的时代,太早进入社会不是好选择
  20. mvdbos php spider,踩坑,windows部署phpspider采集,报错:failed to open stream

热门文章

  1. 带通 带阻滤波器 幅频响应_二阶有源带通滤波器设计
  2. JZOJ 4919. 【NOIP2017提高组模拟12.10】神炎皇
  3. 计算机工程毕业论文任务书,(计算机工程毕业设计论文任务书开题报告模板.doc...
  4. cadence 常见pcb电阻_经验分享|高频PCB设计中出现的干扰分析及对策
  5. vb6 打印选项对话框_办公必备技能,Word打印问题及解决方案全在这,轻松解决打印难题...
  6. Social network Social computing(社会网络和社会计算)
  7. 文本分类入门(九)文本分类问题的分类
  8. [codevs 1907] 方格取数3
  9. 矩阵的基本概念(等价、合同、秩...)
  10. poj1743(后缀数组:最长不可重叠子串长度)