Apakah ada cara untuk menentukan file persis yang berisi unit alokasi dalam grup file beberapa file?

13

Saya berharap untuk mendapatkan tampilan terperinci dari file database mana yang berisi unit alokasi mana untuk berbagai HoBT (baik yang selaras maupun tidak selaras) yang hidup dalam database.

Kueri yang selalu saya gunakan (lihat di bawah) telah membantu saya dengan baik sampai kami mulai membuat beberapa file data per filegroup dan saya hanya bisa mengetahui cara mendapatkan granular seperti pada level filegroup.

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;

Namun, kueri ini tidak akan berfungsi ketika ada beberapa file dalam sebuah grup file karena saya hanya bisa sejauh menghubungkan unit alokasi ke ruang data dan, pada akhirnya, sebuah grup file. Saya ingin tahu apakah ada DMV atau katalog lain yang saya lewatkan yang dapat saya gunakan untuk mengidentifikasi lebih lanjut file mana dalam filegroup yang berisi unit alokasi.

Pertanyaan di balik pertanyaan ini adalah bahwa saya mencoba untuk mengevaluasi efek aktual dari kompresi struktur yang dipartisi. Saya tahu saya bisa melakukan sebelum dan sesudah menggunakan FILEPROPERTY(FileName,'SpaceUsed')untuk file dan sebelum dan sesudah sys.allocation_units.used_pages/128.untuk mendapatkan informasi ini, tetapi latihan itu sendiri membuat saya bertanya-tanya apakah saya bisa mengidentifikasi file tertentu yang berisi unit alokasi tertentu.

Saya telah bermain-main dengan %%physloc%%harapan itu bisa membantu, tetapi itu tidak cukup untuk mendapatkan apa yang saya cari. Tautan di bawah ini disediakan oleh Aaron Bertrand :

swasheck
sumber

Jawaban:

11

Coba kueri berikut. Pertama-tama membuat tabel sementara lokal dan kemudian mengisinya dengan asosiasi AllocationUnitID-to-FileID yang ditemukan di sys.dm_db_database_page_allocations, Fungsi Manajemen Dinamis (DMF) tidak berdokumen yang diperkenalkan di SQL Server 2012 (untuk versi sebelum 2012, Anda bisa mendapatkan info ini dari DBCC IND()). Tabel temp lokal itu kemudian BERGABUNG ke dalam versi modifikasi dari kueri asli.

Data dari DMF itu ditempatkan ke dalam tabel sementara untuk kinerja karena, tergantung pada ukuran database, itu bisa memakan waktu lebih dari beberapa detik untuk mendapatkan data itu. Kata DISTINCTkunci digunakan karena DMF mengembalikan satu baris per halaman data, dan ada beberapa halaman data per setiap unit alokasi.

Saya meninggalkan-GABUNG data itu ke dalam kueri asli karena kueri asli mengembalikan unit alokasi yang memiliki 0 halaman data (biasanya ROW_OVERFLOW_DATAdan LOB_DATAjenis). Saya juga menambahkan total_pagesbidang sehingga akan lebih mudah untuk menghubungkan titik data ke baris yang ada NULLuntuk File Data. Jika Anda tidak peduli dengan Unit Alokasi yang memiliki 0 baris, maka tidak apa-apa untuk mengubahnya LEFT JOINmenjadi 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;
Solomon Rutzky
sumber
Ini alat yang hebat, terima kasih. Saya ingin menunjukkan bahwa kolom TotalPages, adalah total halaman untuk indeks. Ketika hasilnya mengembalikan beberapa baris per indeks, indeks tersebar di beberapa file, tetapi itu tidak menunjukkan berapa banyak indeks pada setiap file. Setiap baris akan menunjukkan jumlah total halaman per indeks, bukan per file. ( Beberapa kali pertama saya menjalankannya, saya pikir, mendinginkan indeks saya seimbang di seluruh file, saya salah )
James Jenkins
1

Remus Rusanu, pada 21 Mei 2013, memberikan jawaban untuk pertanyaan ini:

Satu filegroup, banyak datafile, cara mendapatkan daftar tabel di setiap file

Jawabannya adalah:

Objek dalam filegroup akan menggunakan semua datafiles di filegroup. Setiap tabel di FG1 berada secara sama di Datafile1, Datafile2 dan Datafile3. Jika Anda perlu mengontrol penempatan, Anda perlu membuat grup grup yang berbeda.

RLF
sumber
Terima kasih. Saya tidak benar-benar ingin mengontrol ke mana ia pergi, tetapi melihat ke mana ia pergi.
swasheck
3
FYI - ini benar dengan asumsi semua file dibuat pada saat yang sama. Jika file ditambahkan ke filegroup atau flag jejak lain digunakan, itu mungkin tidak ada di semua file. Tidak mengatakan dia salah, karena dia tidak, mengatakan bahwa itu tergantung :)
Sean Gallardy