Чи існує спосіб визначити точний файл, який містить одиницю розподілу у групі файлів з декількох файлів?


13

Я сподівався отримати детальне уявлення про те, які файли баз даних містять одиниці розподілу для різних HoBT (як вирівняні, так і нерівні), що живуть у базі даних.

Запит, який я завжди використовував (див. Нижче), мені добре служив, поки ми не почали створювати декілька файлів даних для кожної файлової групи, і я можу лише зрозуміти, як отримати настільки детальний, як рівень файлової групи.

select 
    SchemaName = sh.name, 
    TableName = t.name, 
    IndexName = i.name, 
    PartitionNumber = p.partition_number,
    IndexID = i.index_id,
    IndexDataspaceID = i.data_space_id,
    AllocUnitDataspaceID = au.data_space_id,
    PartitionRows = p.rows
from sys.allocation_units au
join sys.partitions p
    on au.container_id = p.partition_id
join sys.indexes i 
    on i.object_id = p.object_id
    and i.index_id = p.index_id
join sys.tables t 
    on p.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where sh.name != 'sys'
    and au.type = 2
union all 
select 
    sh.name, 
    t.name, 
    i.name, 
    p.partition_number,
    i.index_id,
    i.data_space_id,
    au.data_space_id,
    p.rows
from sys.allocation_units au
join sys.partitions p
    on au.container_id = p.hobt_id
join sys.indexes i 
    on i.object_id = p.object_id
    and i.index_id = p.index_id
join sys.tables t 
    on p.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where sh.name != 'sys'
    and au.type in (1,3)
order by t.name, i.index_id,p.partition_number;

Однак цей запит не працюватиме, коли у групі файлів є декілька файлів, оскільки я можу дістати лише так, щоб відновити одиницю розподілу до простору даних і, зрештою, групу файлів. Мені хотілося б дізнатися, чи є ще один DMV або каталог, який мені не вистачає, і я можу використати для подальшого визначення того, який файл у групі файлів містить одиницю розподілу.

Питання, що стоїть за цим питанням, полягає в тому, що я намагаюся оцінити фактичний ефект стискання перегороджених конструкцій. Я знаю, що я можу зробити до і після використання FILEPROPERTY(FileName,'SpaceUsed')для файлу та перед і після, sys.allocation_units.used_pages/128.щоб отримати цю інформацію, але сама вправа змусила мене задуматися, чи можу я визначити конкретний файл, який містить певний блок розподілу.

Я возився з %%physloc%%надією, що це може допомогти, але це не зовсім мені приносить те, чого я прагну. Посилання нижче були надані Аароном Бертрандом :


Відповіді:


11

Спробуйте наступний запит. Спочатку створюється локальна тимчасова таблиця, а потім заповнюється її асоціаціями AllocationUnitID-to-FileID, знайденими в sys.dm_db_database_page_allocationsнедокументованій функції динамічного управління (DMF), запровадженої в SQL Server 2012 (для версій до 2012 року ви можете отримати цю інформацію від DBCC IND()). Ця локальна таблиця темпів потім приєднується до модифікованої версії оригінального запиту.

Дані з цього DMF поміщаються у тимчасову таблицю для продуктивності, оскільки, залежно від розміру бази даних, на отримання цих даних може знадобитися більше декількох секунд. DISTINCTВикористовується ключове слово , тому що ДМФ повертає один рядок для кожної сторінки даних, і існує безліч сторінок даних в кожній одиниці виділення.

Я залишив-ПРИЄДНАЙТЕСЬ ці дані у вихідний запит, оскільки оригінальний запит повертає одиниці розподілу, які містять 0 сторінок даних (як правило, ROW_OVERFLOW_DATAі LOB_DATAтипів). Я також додав total_pagesполе, щоб було простіше співвіднести цю точку даних до рядків, які мають NULLs для файлів даних. Якщо вам не байдуже одиниці розподілу, що мають 0 рядків, було б добре змінити це LEFT JOINна " рядок " INNER JOIN.

IF (OBJECT_ID(N'tempdb..#AllocationsToFiles') IS NULL)
BEGIN
    -- DROP TABLE #AllocationsToFiles;
    CREATE TABLE #AllocationsToFiles
    (
      ObjectID INT NOT NULL,
      IndexID INT NOT NULL,
      PartitionID INT NOT NULL,
      RowsetID BIGINT NOT NULL,
      AllocationUnitID BIGINT NOT NULL,
      AllocatedPageFileID SMALLINT NOT NULL
    );
END;

IF (NOT EXISTS(SELECT * FROM #AllocationsToFiles))
BEGIN
  --TRUNCATE TABLE #AllocationsToFiles;
  INSERT INTO #AllocationsToFiles (ObjectID, IndexID, PartitionID, RowsetID,
                                   AllocationUnitID, AllocatedPageFileID)
    SELECT DISTINCT alloc.[object_id], alloc.[index_id], alloc.[partition_id],
           alloc.[rowset_id], alloc.[allocation_unit_id], alloc.[allocated_page_file_id]
    FROM   sys.dm_db_database_page_allocations(DB_ID(), NULL, NULL, NULL,
                                               'LIMITED') alloc
    WHERE  alloc.is_allocated = 1
    AND    alloc.is_iam_page = 0;
END;

SELECT
    SchemaName = sh.name, 
    TableName = t.name, 
    IndexName = i.name, 
    PartitionNumber = p.partition_number,
    IndexID = i.index_id,
    IndexDataspaceID = i.data_space_id,
    AllocUnitDataspaceID = au.data_space_id,
    PartitionRows = p.[rows],
    TotalPages = au.total_pages,
    AllocationUnitType = au.type_desc,
    LogicalFileName = dbf.[name],
    PhysicalFileName = dbf.[physical_name]
    --,p.[object_id], p.[partition_id], au.allocation_unit_id
FROM sys.allocation_units au
INNER JOIN sys.partitions p
        ON au.container_id = IIF(au.[type] = 2, p.[partition_id], p.[hobt_id])
INNER JOIN sys.indexes i 
        ON i.[object_id] = p.[object_id]
       AND i.index_id = p.index_id
INNER JOIN sys.tables t 
        ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas sh
        ON t.[schema_id] = sh.[schema_id]
LEFT JOIN (#AllocationsToFiles alloc
       INNER JOIN sys.database_files dbf
               ON dbf.[file_id] = alloc.AllocatedPageFileID
          ) 
        ON alloc.ObjectID = p.[object_id]
       AND alloc.IndexID = p.index_id
       AND alloc.PartitionID = p.partition_number
       AND alloc.AllocationUnitID = au.allocation_unit_id
WHERE sh.name <> N'sys'
ORDER BY t.name, i.index_id, p.partition_number;

Це чудовий інструмент, дякую. Я хочу зазначити, що стовпець TotalPages - це загальна кількість сторінок для індексу. Коли результати повертають кілька рядків на індекс, індекс розподіляється на кілька файлів, але він не показує, яка частина індексу є у кожному файлі. У кожному рядку відображатиметься загальна кількість сторінок на індекс, а не на файл. ( Перші кілька разів я запускав це, я думав, круто мої індекси ідеально збалансовані між файлами, я помилявся )
Джеймс Дженкінс

1

21 травня 2013 року Ремус Русану дав відповідь на це питання:

Одна файлова група, кілька файлів даних, як отримати список таблиць у кожному файлі

Його відповідь:

Об'єкт у групі файлів буде використовувати всі файли даних у групі файлів. Будь-яка таблиця у FG1 однаково розташована на Datafile1, Datafile2 та Datafile3. Якщо вам потрібно контролювати місця розташування, вам потрібно створити різні групи файлів.


Спасибі. Я не дуже хочу контролювати, куди йде, а радше бачу, куди воно пішло.
swasheck

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