我正在尝试获取具有 ROW_OVERFLOW_DATA 行的表的页面列表。我可以从未记录的 DMV 中获取已分配页面的列表sys.db_db_database_page_allocations
,但是,该 DMV 的输出中似乎没有列出 ROW_OVERFLOW_DATA 页面。还有其他一些我根本找不到的 DMV 吗?
最小的、完整的和(希望!)可验证的示例:
USE tempdb;
IF OBJECT_ID(N'dbo.t', N'U') IS NOT NULL
DROP TABLE dbo.t;
GO
CREATE TABLE dbo.t
(
rownum int NOT NULL IDENTITY(1,1)
PRIMARY KEY CLUSTERED
, on_row_data varchar(30) NOT NULL
DEFAULT ('on_row_data')
, off_row_data varchar(MAX) NOT NULL
DEFAULT REPLICATE('A', 20000) --PLENTY BIG ENOUGH!
) WITH (DATA_COMPRESSION = NONE); --not compressing those pages!
INSERT INTO dbo.t DEFAULT VALUES;
DECLARE @ObjectID int = (SELECT o.object_id FROM sys.objects o WHERE o.name = 't');
DECLARE @PageID int;
DECLARE @PageTypeDesc varchar(100);
SELECT FileID = dpa.allocated_page_file_id
, PageID = dpa.allocated_page_page_id
, PageTypeDesc = dpa.page_type_desc
FROM sys.dm_db_database_page_allocations(DB_ID(), @ObjectID, NULL, NULL, 'DETAILED') dpa
输出看起来像:
╔════════╦════════╦══════════════╗ ║ 文件 ID ║ 页面 ID ║ PageTypeDesc ║ ╠════════╬════════╬══════════════╣ ║ 1 ║ 1598 ║ IAM_PAGE ║ ║ 3 ║ 105368 ║ DATA_PAGE ║ ║ 3 ║ 105369 ║ 空 ║ ║ 3 ║ 105370 ║ 空 ║ ║ 3 ║ 105371 ║ 空 ║ ║ 3 ║ 105372 ║ 空 ║ ║ 3 ║ 105373 ║ 空 ║ ║ 3 ║ 105374 ║ 空 ║ ║ 3 ║ 105375 ║ 空 ║ ╚════════╩════════╩══════════════╝
这是有道理的,除了缺少 ROW_OVERFLOW_DATA 页面。我们有一个单独的索引分配映射页面,以及一个完整的 8KB 数据页面,其中只有一个实际分配了页面。
同样,如果我使用未记录的sys.fn_PhysLocCracker
函数来显示每行所在的页面,如:
SELECT *
FROM dbo.t
CROSS APPLY sys.fn_PhysLocCracker(%%PHYSLOC%%)
我只看到DATA_PAGE
列出的:
╔════════╦═════════════╦═════════════════════╦════ ═════╦═════════╦═════════╗ ║ rownum ║ on_row_data ║ off_row_data ║ file_id ║ page_id ║ slot_id ║ ╠════════╬═════════════╬═════════════════════╬════ ═════╬═════════╬═════════╣ ║ 1 ║ on_row_data ║ AAAAAAAAAAAAAAAAAAA ║ 3 ║ 105368 ║ 0 ║ ╚════════╩═════════════╩═════════════════════╩════ ═════╩═════════╩═════════╝
同样,如果我使用,DBCC IND(database, table, index)
我只会看到列出的两个页面:
DBCC IND (tempdb, t, 1);
输出:
╔═════════╦═════════╦════════╦════════╦═══════════ ═╦═════════╦═════════════════╦════════════════════ ═╦════════════════╦══════════╦════════════╦═══════ ══════╦═════════════╦═════════════╦═════════════╦═ ═╗ ║ PageFID ║ PagePID ║ IAMFID ║ IAMPID ║ ObjectID ║ IndexID ║ PartitionNumber ║ PartitionID ║ iam_chain_type ║ PageType ║ IndexLevel ║ NextPageFID ║ NextPagePID ║ PrevPageFID ║ PrevPagePID ║ ║ ╠═════════╬═════════╬════════╬════════╬═══════════ ═╬═════════╬═════════════════╬════════════════════ ═╬════════════════╬══════════╬════════════╬═══════ ══════╬═════════════╬═════════════╬═════════════╬═ ═╣ ║ 1 ║ 1598 ║ NULL ║ NULL ║ 2069582411 ║ 1 ║ 1 ║ 6989586877272752128 ║ 行内数据 ║ 10 ║ NULL ║ 0 ║ 0 ║ 0 ║ 0 ║ ║ 3 ║ 105368 ║ 1 ║ 1598 ║ 2069582411 ║ 1 ║ 1 ║ 6989586877272752128 ║ 行内数据 ║ 1 ║ 0 ║ 0 ║ 0 ║ 0 ║ ║ ╚═════════╩═════════╩════════╩════════╩═══════════ ═╩═════════╩═════════════════╩════════════════════ ═╩════════════════╩══════════╩════════════╩═══════ ══════╩═════════════╩═════════════╩═════════════╩═ ═╝
如果我查看实际页面内容,使用DBCC PAGE
,看起来我仍然看不到关于哪个页面包含 ROW_OVERFLOW_DATA 的任何信息 - 我确定它一定在那里,我可能只是不知道要看什么:
DBCC PAGE (tempdb, 3, 105368 , 3) WITH TABLERESULTS;
如果我包括内存转储行,结果太大而不适合这里,但这是标头输出:
╔══════════════╦════════════════════════════════╦═ ══════════════════════════════╦═══════════════════ ════════════╗ ║ 父对象 ║ 对象 ║ 字段 ║ 值 ║ ╠══════════════╬════════════════════════════════╬═ ══════════════════════════════╬═══════════════════ ════════════╣ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bpage ║ 0x000002431A8A2000 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bhash ║ 0x0000000000000000 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bpageno ║ (3:105368) ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bdbid ║ 2 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ 参考 ║ 0 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bcputicks ║ 0 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bsampleCount ║ 0 ║ ║ 缓冲器: ║ BUF @0x000002437E86D5C0 ║ bUse1 ║ 63172 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bstat ║ 0x10b ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ 博客 ║ 0x212121cc ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bnext ║ 0x0000000000000000 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bDirtyContext ║ 0x000002435DA77160 ║ ║ 缓冲区: ║ BUF @0x000002437E86D5C0 ║ bstat2 ║ 0x0 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_pageId ║ (3:105368) ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_headerVersion ║ 1 ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_type ║ 1 ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_typeFlagBits ║ 0x0 ║ ║页眉:║页@0x000002431A8A2000║m_level║0║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_flagBits ║ 0xc000 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_objId (AllocUnitId.idObj) ║ 3920762 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_indexId (AllocUnitId.idInd) ║ 512 ║ ║页眉:║页面@0x000002431A8A2000║元数据:AllocUnitId║144115445026914304║ ║页眉:║页面@0x000002431A8A2000║元数据:PartitionId║6989586877272752128║ ║ 页眉:║ 页 @0x000002431A8A2000 ║ 元数据:IndexId ║ 1 ║ ║页眉:║页面@0x000002431A8A2000║元数据:ObjectId║2069582411║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_prevPage ║ (0:0) ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_nextPage ║ (0:0) ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ pminlen ║ 8 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_slotCnt ║ 1 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_freeCnt ║ 66 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_freeData ║ 8124 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_reservedCnt ║ 0 ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_lsn ║ (36:47578:1) ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_xactReserved ║ 0 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_xdesId ║ (0:0) ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ m_ghostRecCnt ║ 0 ║ ║ 页眉: ║ 页@0x000002431A8A2000 ║ m_tornBits ║ 0 ║ ║ 页眉: ║ 页 @0x000002431A8A2000 ║ 数据库片段 ID ║ 1 ║ ║ 页眉: ║ 分配状态 ║ GAM (3:2) ║ 已分配 ║ ║ 页眉: ║ 分配状态 ║ SGAM (3:3) ║ 未分配 ║ ║ 页眉: ║ 分配状态 ║ PFS (3:105144) ║ 0x40 ALLOCATED 0_PCT_FULL ║ ║ 页眉: ║ 分配状态 ║ 差异 (3:6) ║ 未更改 ║ ║ 页眉: ║ 分配状态 ║ ML (3:7) ║ NOT MIN_LOGGED ║ ║ PAGE HEADER: ║ Slot 0 Offset 0x60 Length 8028 ║ Record Type ║ PRIMARY_RECORD ║ ║ PAGE HEADER: ║ Slot 0 Offset 0x60 Length 8028 ║ Record Attributes ║ NULL_BITMAP VARIABLE_COLUMNS ║ ║ 页眉: ║ 槽 0 偏移量 0x60 长度 8028 ║ 记录大小 ║ 8028 ║ ╚══════════════╩════════════════════════════════╩═ ══════════════════════════════╩═══════════════════ ════════════╝
您的演示受到REPLICATE 限制的影响:
如果我这样做:
然后从上方针对 dm_db_database_page_allocations 运行您的 DMV 查询,我得到 PageTypeDesc 为
TEXT_MIX_PAGE
.然后,我可以在启用跟踪标志 3604 的情况下运行 DBCC PAGE,以查看该行外页面的详细信息:
输出很大,但在开始附近您会看到:
然后,你知道,一堆 A。