内部表
SQL Server 将自动创建内部表以支持下列功能:
主 XML 索引
空间索引
Service Broker
查询通知
更改跟踪
内部表是某些其他用户操作所产生的副产品。例如,创建主 XML 索引时,SQL Server 将自动创建一个内部表以保存拆分的 XML 文档数据。内部表出现在每个数据库的 sys 架构中,具有指示其功能的由系统生成的专有名称,例如 xml_index_nodes_2021582240_32001 或 queue_messages_1977058079。
内部表不包括用户可访问的数据,并且其架构是固定的,不可改变。不能在 Transact-SQL 语句中引用内部表名称。例如,不能执行 SELECT * FROM <sys.internal_table_name> 之类的语句。但是,可以查询目录视图以查看内部表的元数据。
查看内部表元数据
使用 sys.internal_tables 目录视图,可以查看与内部表关联的元数据。使用此视图,可以查看内部表的架构。由于内部表与用户表具有许多相同的特征,因此 sys.internal_tables 视图继承了 sys.objects 目录视图中的列,并具有类型“IT”。与用户表一样,可以在 sys.columns 目录视图中查看内部表的列元数据,在 sys.indexes 和 sys.stats 目录视图中查看内部表的由系统生成的索引和统计信息的元数据。
通过联接到其他目录视图,还可以获取有关分配和空间利用率的信息。请参阅本主题后面的“内部表存储”。
下图显示了顶级目录数据模型。
查看内部表元数据的权限
若要查看数据库的内部表元数据,您需要具有下列一种权限和组成员身份:
CONTROL SERVER 权限。
数据库中的 CONTROL 权限。
db_owner 或 sysadmin 组中的成员身份。
可以查看父实体(XML 索引、空间索引或队列)的用户可以查看此实体的内部表。
查看 XML 索引元数据
下图显示了 XML 索引内部表的元数据结构。
为了理解图中所示的目录视图关系,假设对表 T 创建了主 XML 索引 Xp。此表的元数据位于 sys.tables 目录视图中,XML 索引的元数据位于 sys.xml_indexes 目录视图中。SQL Server 创建以保存 XML 索引数据的内部表 Ti 的元数据位于 sys.internal_tables 视图中。
若要查找内部表 Ti 和用户表 T 之间的关系,可以将 sys.internal_tables 视图的 parent_id 列联接到 sys.tables 视图的 object_id 列。若要查找内部表 Ti 和 XML 索引 Xp 之间的关系,可以将 sys.internal_tables 的 parent_id 和 parent_minor_id 列联接到 sys.xml_indexes 的 object_id 和 index_id 列。请参阅下面的示例 G。
查看空间索引元数据
空间索引的元数据与 XML 索引的元数据大部分相同。区别在于空间索引使用 sys.spatial_indexes 而非 sys.xml_indexes,并且您需要使用 sys.spatial_index_tessellations 才能查看空间索引的空间参数。
下图显示了空间索引内部表的元数据结构。
为了理解图中所示的目录视图关系,假设对表 T 创建了空间索引 Si。此表的元数据位于 sys.tables 目录视图中,空间索引的元数据位于 sys.spatial_indexes 目录视图和 sys.spatial_index_tessellations 目录视图中。SQL Server 为保存空间索引数据而创建的内部表 Ti 的元数据位于 sys.internal_tables 视图中。
若要查找内部表 Ti 和用户表 T 之间的关系,可以将 sys.internal_tables 视图的 parent_id 列联接到 sys.tables 视图的 object_id 列。若要查找内部表 Ti 和空间索引 Si 之间的关系,可以将 sys.internal_tables 的 parent_id 和 parent_minor_id 列联接到 sys.spatial_indexes 的 object_id 和 index_id 列。有关详细信息,请参阅本主题后面的示例 L。
查看 Service Broker 元数据
下图显示了 Service Broker 队列内部表的元数据结构。Service Broker 消息、查询通知和事件通知都使用 Service Broker 队列。此外,Service Broker 功能还使用内部表存储有关所有数据库中的所有 Service Broker 服务的信息。此内部表位于 tempdb 系统数据库中。
查看查询通知元数据
下图显示了查询通知订阅内部表的元数据结构。内部表用于存储查询通知订阅的参数。
内部表存储
内部表与父实体位于同一文件组。可以使用下面示例 F 中所示的目录查询返回内部表中用于行内数据、行外数据和大型对象 (LOB) 数据的页数。
可以使用 sp_spaceused 系统过程返回内部表的空间使用情况数据。sp_spaceused 以下列方式报告内部表空间:
当指定队列名称时,将引用与队列关联的基础内部表并报告其存储空间使用情况。
XML 索引、空间索引和全文索引的内部表所使用的页包括在 index_size 列中。当指定表或索引视图名称时,此对象的 XML 索引、空间索引和全文索引的页包括在 reserved 和 index_size 列中。
示例
下列示例说明如何使用目录视图查询内部表元数据。
A. 显示继承 sys.objects 目录视图中的列的内部表
SELECT * FROM sys.objects WHERE type = 'IT';
B. 返回所有内部表元数据(包括从 sys.objects 中继承的元数据)
SELECT * FROM sys.internal_tables;
C. 返回内部表列和列数据类型
SELECT SCHEMA_NAME(itab.schema_id) AS schema_name
,itab.name AS internal_table_name
,typ.name AS column_data_type
,col.*
FROM sys.internal_tables AS itab
JOIN sys.columns AS col ON itab.object_id = col.object_id
JOIN sys.types AS typ ON typ.user_type_id = col.user_type_id
ORDER BY itab.name, col.column_id;
D. 返回内部表索引
SELECT SCHEMA_NAME(itab.schema_id) AS schema_name
, itab.name AS internal_table_name
, idx.*
FROM sys.internal_tables AS itab
JOIN sys.indexes AS idx ON itab.object_id = idx.object_id
ORDER BY itab.name, idx.index_id;
E. 返回内部表统计信息
SELECT SCHEMA_NAME(itab.schema_id) AS schema_name
,itab.name AS internal_table_name
, s.*
FROM sys.internal_tables AS itab
JOIN sys.stats AS s ON itab.object_id = s.object_id
ORDER BY itab.name, s.stats_id;
F. 返回内部表分区和分配单元信息
SELECT SCHEMA_NAME(itab.schema_id) AS schema_name
,itab.name AS internal_table_name
,idx.name AS heap_or_index_name
,p.*
,au.*
FROM sys.internal_tables AS itab
JOIN sys.indexes AS idx
-- JOIN to the heap or the clustered index
ON itab.object_id = idx.object_id AND idx.index_id IN (0,1)
JOIN sys.partitions AS p
ON p.object_id = idx.object_id AND p.index_id = idx.index_id
JOIN sys.allocation_units AS au
-- IN_ROW_DATA (type 1) and ROW_OVERFLOW_DATA (type 3) => JOIN to partition's Hobt
-- else LOB_DATA (type 2) => JOIN to the partition ID itself.
ON au.container_id =
CASE au.type
WHEN 2 THEN p.partition_id
ELSE p.hobt_id
END
ORDER BY itab.name, idx.index_id;
G. 返回 XML 索引的内部表元数据
SELECT t.name AS parent_table
,t.object_id AS parent_table_id
,it.name AS internal_table_name
,it.object_id AS internal_table_id
,xi.name AS primary_XML_index_name
,xi.index_id as primary_XML_index_id
FROM sys.internal_tables AS it
JOIN sys.tables AS t
ON it.parent_id = t.object_id
JOIN sys.xml_indexes AS xi
ON it.parent_id = xi.object_id
AND it.parent_minor_id = xi.index_id
WHERE it.internal_type_desc = 'XML_INDEX_NODES';
GO
H. 返回 Service Broker 队列的内部表元数据
SELECT q.name AS queue_name
,q.object_id AS queue_id
,it.name AS internal_table_name
,it.object_id AS internal_table_id
FROM sys.internal_tables AS it
JOIN sys.service_queues AS q ON it.parent_id = q.object_id
WHERE it.internal_type_desc = 'QUEUE_MESSAGES';
GO
I. 返回所有 Service Broker 服务的内部表元数据
SELECT *
FROM tempdb.sys.internal_tables
WHERE internal_type_desc = 'SERVICE_BROKER_MAP';
GO
J. 返回查询通知订阅的内部表元数据
SELECT qn.id AS query_subscription_id
,it.name AS internal_table_name
,it.object_id AS internal_table_id
FROM sys.internal_tables AS it
JOIN sys.dm_qn_subscriptions AS qn ON it.object_id = qn.object_id
WHERE it.internal_type_desc = 'QUERY_NOTIFICATION';
K. 返回空间索引的内部表元数据
SELECT t.name AS parent_table
,t.object_id AS parent_table_id
,it.name AS internal_table_name
,it.object_id AS internal_table_id
,si.name AS spatial_index_name
,si.index_id as spatial_index_id
FROM sys.internal_tables AS it
JOIN sys.tables AS t
ON it.parent_id = t.object_id
JOIN sys.spatial_indexes AS si
ON it.parent_id = si.object_id
AND it.parent_minor_id = si.index_id
WHERE it.internal_type_desc = 'EXTENDED_INDEXES';
GO