Share via


內部資料表

SQL Server 會自動建立內部資料表來支援下列功能:

  • 主要 XML 索引

  • 空間索引

  • Service Broker

  • 查詢通知

  • 變更追蹤

內部資料表是某些其他使用者動作的副作用。例如,當您建立主要 XML 索引時,SQL Server 就會自動建立內部資料表來保存零碎的 XML 文件資料。內部資料表會出現在每個資料庫的 sys 結構描述中,而且會具有系統產生的唯一名稱,以便表示其功能,例如 xml_index_nodes_2021582240_32001queue_messages_1977058079

內部資料表不包含使用者可存取的資料,而且其結構描述是固定且無法變更的。您無法在 Transact-SQL 陳述式中參考內部資料表名稱。例如,您無法執行 SELECT * FROM <sys.internal_table_name> 等陳述式。不過,您可以查詢目錄檢視來查看內部資料表的中繼資料。

檢視內部資料表中繼資料

您可以使用 sys.internal_tables 目錄檢視,藉以檢視與內部資料表相關聯的中繼資料。透過這項檢視,您就可以檢視內部資料表的結構描述。由於內部資料表與使用者資料表具有許多相同的特性,因此 sys.internal_tables 檢視會從 sys.objects 目錄檢視繼承資料行並且具有 'IT' 的類型。如同使用者資料表一樣,內部資料表的資料行中繼資料可在 sys.columns 目錄檢視中檢視,而且內部資料表上系統產生之索引和統計資料的中繼資料可在 sys.indexessys.stats 目錄檢視中檢視。

您也可以透過聯結至其他目錄檢視,取得有關配置和空間使用的資訊。請參閱本主題後面的「內部資料表儲存」。

下圖將顯示最上層的目錄資料模型。

內部資料表目錄檢視的圖表

檢視內部資料表中繼資料的權限

若要檢視資料庫中的內部資料表中繼資料,您會需要下列其中一項權限或群組成員資格:

  • CONTROL SERVER 權限。

  • 資料庫中的 CONTROL 權限。

  • db_ownersysadmin 群組中的成員資格。

  • 可以檢視父實體 (XML 或空間索引或佇列) 的使用者就可以檢視該實體的內部資料表。

檢視 XML 索引中繼資料

下圖將顯示 XML 索引之內部資料表的中繼資料結構。

XML 索引目錄檢視的圖表

若要了解本圖中顯示的目錄檢視關聯性,請假設主要 XML 索引 Xp 是在資料表 T 上建立的。資料表的中繼資料是位於 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_tablesparent_idparent_minor_id 資料行聯結至 sys.xml_indexesobject_idindex_id 資料行。請參閱下面的範例 G。

檢視空間索引中繼資料

空間索引的中繼資料大多與 XML 索引的中繼資料相等。兩者的差異在於空間索引會使用 sys.spatial_indexes 而不是 sys.xml_indexes,而且您需要使用 sys.spatial_index_tessellations 來檢視空間索引的空間參數。

下圖將顯示空間索引上內部資料表的中繼資料結構。

空間索引目錄檢視圖表

若要了解本圖中顯示的目錄檢視關聯性,請假設空間索引 Si 是在資料表 T 上建立的。資料表的中繼資料是位於 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_tablesparent_idparent_minor_id 資料行聯結至 sys.spatial_indexesobject_idindex_id 資料行。如需詳細資訊,請參閱這個主題稍後的範例 L。

檢視 Service Broker 中繼資料

下圖將顯示 Service Broker 佇列之內部資料表的中繼資料結構。Service Broker 訊息、查詢通知和事件通知都會使用 Service Broker 佇列。此外,Service Broker 功能也會使用內部資料表來儲存所有資料庫中所有 Service Broker 服務的相關資訊。此內部資料表是位於 tempdb 系統資料庫中。

Service Broker 目錄檢視的圖表

檢視查詢通知中繼資料

下圖將顯示查詢通知訂閱之內部資料表的中繼資料結構。內部資料表是用來儲存查詢通知訂閱的參數。

查詢通知目錄檢視的圖表

內部資料表儲存

內部資料表會與父實體放置於相同的檔案群組中。您可以使用下列範例 F 中顯示的目錄查詢,傳回內部資料表針對同資料列、資料列外和大型物件 (LOB) 資料所使用的頁面數。

您可以使用 sp_spaceused 系統程序來傳回內部資料表的空間使用資料。sp_spaceused 會使用下列方式來報告內部資料表的空間:

  • 當您指定佇列名稱後,就會參考與此佇列相關聯的基礎內部資料表,並且報告其儲存耗用量。

  • XML 索引、空間索引和全文檢索索引之內部資料表所使用的頁面會包含在 index_size 資料行中。當您指定資料表或索引檢視表名稱後,該物件之 XML 索引、空間索引和全文檢索索引的頁面就會包含在資料行 reservedindex_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