Перерахуйте ROW_OVERFLOW_DATA сторінки для певної таблиці


11

Я намагаюся отримати список сторінок для таблиці, що має рядки з ROW_OVERFLOW_DATA. Я можу отримати список виділених сторінок із недокументованого DMV, sys.db_db_database_page_allocationsоднак, схоже, немає ROW_OVERFLOW_DATA сторінок, перелічених у висновку цього DMV. Чи є якісь інші 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

Результат виглядає так:

╔════════╦════════╦══════════════╗
║ FileID ║ PageID ║ PageTypeDesc ║
╠════════╬════════╬══════════════╣
║ 1 ║ 1598 ║ IAM_PAGE ║
║ 3 ║ 105368 ║ DATA_PAGE ║
║ 3 ║ 105369 ║ NULL ║
║ 3 ║ 105370 ║ NULL ║
║ 3 ║ 105371 ║ NULL ║
║ 3 ║ 105372 ║ NULL ║
║ 3 ║ 105373 ║ NULL ║
║ 3 ║ 105374 ║ NULL ║
║ 3 ║ 105375 ║ NULL ║
╚════════╩════════╩══════════════╝

Що має сенс, окрім відсутньої сторінки ROW_OVERFLOW_DATA. У нас є одна карта карти розподілу індексів і повна розширення на 8 КБ сторінок даних, лише одна з цих сторінок фактично виділена.

Аналогічно, якщо я використовую недокументовану 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 ║ AAAAAAAAAAAAAAAAAAAA ║ 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 data Дані в рядках ║ 10 ║ NULL ║ 0 ║ 0 ║ 0 ║ 0 ║ ║
║ 3 ║ 105368 ║ 1 ║ 1598 ║ 2069582411 ║ 1 ║ 1 ║ 6989586877272752128 data Дані про рядки ║ 1 ║ 0 ║ 0 ║ 0 ║ 0 ║ 0 ║ ║
╚═════════╩═════════╩════════╩════════╩═══════════ ═╩═════════╩═════════════════╩════════════════════ ═╩════════════════╩══════════╩════════════╩═══════ ══════╩═════════════╩═════════════╩═════════════╩═ ═╝

Якщо я дивлюсь на фактичний вміст сторінки, використовуючи DBCC PAGE, то виглядає так, що я все ще не бачу нічого, на якій сторінці міститься ROW_OVERFLOW_DATA - я впевнений, що він повинен бути там, я, мабуть, просто не знаю, на що дивитись:

DBCC PAGE (tempdb, 3, 105368 , 3) WITH TABLERESULTS;

Результати занадто великі, щоб відповідати тут, якщо я включаю ряди дампів пам'яті, але це вихідний заголовок:

╔══════════════╦════════════════════════════════╦═ ══════════════════════════════╦═══════════════════ ════════════╗
║ ParentObject ║ Object ║ Поле ║ VALUE ║
╠══════════════╬════════════════════════════════╬═ ══════════════════════════════╬═══════════════════ ════════════╣
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bpage ║ 0x000002431A8A2000 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ha bhash ║ 0x0000000000000000 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bpageno ║ (3: 105368) ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bdbid ║ 2 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ braferences ║ 0 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bcputicks ║ 0 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bsampleCount ║ 0 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bUse1 ║ 63172 ║
║ БУФЕР: ║ BUF @ 0x000002437E86D5C0 ║ bstat ║ 0x10b ║
║ БУФЕР: ║ BUF @ 0x000002437E86D5C0 ║ блог ║ 0x212121cc ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ne наступний ║ 0x0000000000000000 ║
║ BUFFER: ║ BUF @ 0x000002437E86D5C0 ║ bDirtyContext ║ 0x000002435DA77160 ║
║ БУФЕР: ║ BUF @ 0x000002437E86D5C0 ║ bstat2 ║ 0x0 ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_pageId ║ (3: 105368) ║
AD СТОРІНКА КОРИСТИКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_headerVersion ║ 1 ║
AD СТОРІННИЙ НАВЧАЛЬНИЙ: ║ Сторінка @ 0x000002431A8A2000 ║ m_type ║ 1 ║
AD СТОРІНКА ЗАГОЛОВНИКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_typeFlagBits ║ 0x0 ║
AD СТОРІННИЙ НАВЧАЛЬНИЙ: ║ Сторінка @ 0x000002431A8A2000 ║ m_level ║ 0 ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_flagBits ║ 0xc000 ║
AD СТОРІНКА КОРИСТИТЕЛЯ: ║ Сторінка @ 0x000002431A8A2000 ║ m_objId (AllocUnitId.idObj) ║ 3920762 ║
HE СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_indexId (AllocUnitId.idInd) ║ 512 ║
AD PAGE HEADER: ║ Сторінка @ 0x000002431A8A2000 ║ Метадані: AllocUnitId ║ 144115445026914304 ║
║ PAGE HEADER: ║ Сторінка @ 0x000002431A8A2000 ║ Метадані: PartitionId ║ 6989586877272752128 ║
AD PAGE HEADER: ║ Сторінка @ 0x000002431A8A2000 ║ Метадані: IndexId ║ 1 ║
AD PAGE HEADER: ║ Сторінка @ 0x000002431A8A2000 ║ Метадані: ObjectId ║ 2069582411 ║
AD СТОРІНКА КОРИСТУВАЧ: ║ Сторінка @ 0x000002431A8A2000 ║ m_prevPage ║ (0: 0) ║
AD СТОРІНКА КОРИСТУВАЧ: ║ Сторінка @ 0x000002431A8A2000 ║ m_nextPage ║ (0: 0) ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ pminlen ║ 8 ║
HE СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_slotCnt ║ 1 ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_freeCnt ║ 66 ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_freeData ║ 8124 ║
AD СТОРІНКА КОРИСТИКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_reservedCnt ║ 0 ║
HE СТОРІНКА КОРИСТУВАЧ: ║ Сторінка @ 0x000002431A8A2000 ║ m_lsn ║ (36: 47578: 1) ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_xactЗарезервовано ║ 0 ║
AD СТОРІННИЙ НАВЧАЛЬНИК: ║ Сторінка @ 0x000002431A8A2000 ║ m_xdesId ║ (0: 0) ║
AD СТОРІНКА КОРИСТИКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_ghostRecCnt ║ 0 ║
AD СТОРІНКА КОРОБКА: ║ Сторінка @ 0x000002431A8A2000 ║ m_tornBits ║ 0 ║
AD СТОРІНКА КОРОБКА:: Сторінка @ 0x000002431A8A2000 ID Ідентифікатор фрагмента БД ║ 1 ║
HE НАВЧАЛЬНА СТРАНИЦІЯ: Status Статус розподілу ║ ІГРА (3: 2) ║ РОЗДІЛЕНО ║
HE СТОРІННИЙ НАВЧАЛЬНИК: Status Статус розподілу ║ SGAM (3: 3) ║ НЕ РОЗДІЛЕНО ║
AD СТОРІНКА КОРИСТУВАЧА: Status Статус розподілу ║ PFS (3: 105144) ║ 0x40 ВЗНАЧЕНО 0_PCT_FULL ║
HE СТОРІНКА КОРОБКА: Status Статус розподілу ║ DIFF (3: 6) ║ НЕ ЗМІНЕНО AN
AD СТОРІННИЙ НАВЧАЛЬНИЙ: Status Статус розподілу ║ ML (3: 7) ║ NOT MIN_LOGGED ║
AD ХАРАКТЕРИСТІКА СТОРІНКИ: ║ Слот 0 Зсув 0x60 Довжина 8028 ║ Тип запису ║ PRIMARY_RECORD ║
║ PAGE HEADER: ║ Слот 0 Зсув 0x60 Довжина 8028 ║ Атрибути запису ║ NULL_BITMAP VARIABLE_COLUMNS ║
║ СТОРІНКА КОРИСТУВАЧ: ║ Слот 0 Зсув 0x60 Довжина 8028 ║ Розмір запису ║ 8028 ║
╚══════════════╩════════════════════════════════╩═ ══════════════════════════════╩═══════════════════ ════════════╝

Відповіді:


10

На вашу демонстрацію потрапляє обмеження REPLICATE :

Якщо вираз string_expression не типу varchar (max) або nvarchar (max), REPLICATE скорочує повернене значення у 8000 байт. Для повернення значень, що перевищують 8000 байт, string_expression необхідно явно передати відповідним типом даних великого значення.

Якщо я це роблю:

INSERT INTO dbo.t (off_row_data) VALUES (REPLICATE(CAST('A' as varchar(max)), 20000));

А потім запустіть ваш запит DMV зверху проти dm_db_database_page_allocations, я отримаю сторінки з PageTypeDesc TEXT_MIX_PAGE.

Потім я можу запустити DBCC PAGE із включеним прапором сліду 3604 для того, щоб побачити деталі цієї сторінки поза рядком:

DBCC TRACEON (3604);
GO
DBCC PAGE (TestDB, 1, 20696 , 3) -- your page will be different :)

Вихід великий, але найближчим часом ви побачите:

Blob row at: Page (1:20696) Slot 0 Length: 3934 Type: 3 (DATA)

А потім, знаєте, купа А.


4
Не було б приємно, якби було попередження про усікання чи щось таке.
Макс Вернон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.