use*_*976 5 sql-server metadata
我正在阅读这篇文章:存储引擎内部:页面剖析。
我有一个数据库MyDB
,数据库中有一个表MyTable
。
我有以下问题:
如果我这样做:
(1) 使用以下查询查找表的对象 ID:
Use MyDB;
select sys.objects.name, sys.objects.object_id from sys.objects where (name = 'MyTable');
Run Code Online (Sandbox Code Playgroud)
(2) 然后使用以下命令查找分配给的所有页面MyTable
:
dbcc ind(MyDB, 'MyTable', -1);
Run Code Online (Sandbox Code Playgroud)
(3)然后在结果表中,我选择其中一个数据页(页类型= 1),并使用以下命令:
DBCC TRACEON(3604);
DBCC PAGE (MyDB, 1, 17386, 3);
Run Code Online (Sandbox Code Playgroud)
那么在步骤(3)的转储内容(页头)中, m_objId
(AllocUnitId.idObj
)字段应该等于步骤(1)中获得的对象ID。那是对的吗?
以及这是否适用于用户表和系统基表,例如sys.syscolpars
基表?
根据我的测试,以上两个结论都是正确的。
元数据:ObjectId 是什么意思?在文章中, 'metadata: objectId' <> m_objId
。但是从我自己的测试来看,'metadata: objectId' 总是等于m_objId
. 为什么?原始文章没有清楚地解释元数据。
我使用的是 SQL Server 2005、2008、2008 R2、2012 和 2014
首先,Paul 在博客文章中提到了这些“元数据”字段:
\n\n\n\n\n请注意,我没有\xe2\x80\x99t 包含以 Metadata: 开头的字段。那 \xe2\x80\x99s 因为它们 \xe2\x80\x99 不是页眉的一部分。在 SQL Server 2005 开发期间,我做了一些主要工作,重写了 DBCC PAGE 的内部结构,为了让使用它的每个人都不必执行所有系统表查找以确定实际对象和索引 ID 是什么,我将 DBCC PAGE 更改为它们在内部并输出结果。
\n
因此,“元数据:ObjectId”字段应始终与实际object_id
来源匹配sys.objects
匹配。
问题的另一部分最终在链接的博客文章中得到了回答,如下所示:
\n\n\n\n\n仅
\nm_objId
适用于 ID 小于 100 的系统表以及从 SQL Server 2000 升级的数据库中的表。对于所有其他表,m_objId
是分配单元 ID 的一部分。
所以m_objId
将匹配系统表(以及从 SQL Server 2000 的升级)。但对于其他人,他说这是“分配单元 ID 的一部分”。这有点模糊。
在这里运行 SQL Server 2017,我可以创建一个带有一个索引页的用户表,并从以下位置获取这两个值:DBCC PAGE
:
m_objId (AllocUnitId.idObj) = 178\nMetadata: ObjectId = 901578250\n
Run Code Online (Sandbox Code Playgroud)\n\n我可以确认 901578250 与中的内容匹配sys.objects
object_id
我可以确认 901578250与此表中的
那么178从哪里来呢?
\n\n经过进一步研究,Paul 发表了另一篇文章:存储引擎内部:如何计算分配单元 ID?
\n\n在其中,他讨论了如何从allocation_unit_id
页眉(sys.allocation_units
m_objId
m_indexId
) 和另一个内部 id 字段。
因此,本质上,在 SQL Server 2000 之后,该m_objId
值只是用于计算 ID 的构建块。allocation_unit
. 它位于页面内部,并不真正映射到其他内容(无论如何与“元数据:ObjectId”的方式不同)。