2013-11-21 22 views
6

W pewnym momencie moje dane na moim serwerze SQL Server miały wkrótce zabraknąć miejsca, więc musiałem dodać drugi plik do grupy danych PRIMARY i ustawić limit wzrostu pierwszego pliku. To spowodowało, że nowe dane trafiły do ​​drugiego pliku, co jest dobre. Teraz chciałbym wiedzieć, które tabele mają dane w pierwszym pliku, dzięki czemu mogę wiedzieć, które tabele zostaną zablokowane podczas migracji tych danych do drugiego pliku. Czy istnieje sposób, aby to zobaczyć?Sprawdź, jakie dane znajdują się w pliku danych SQL Server?

Odpowiedz

14

Załączam przykładową bazę danych, który przypomina swoją sytuację.

-- Create database 
CREATE DATABASE [out_of_space] 
ON PRIMARY 
(NAME = N'out_of_space_dat', FILENAME = N'C:\mssql\data\out_of_space_dat.mdf' , SIZE = 4MB , FILEGROWTH = 1MB, MAXSIZE = 4MB) 
LOG ON 
(NAME = N'out_of_space_log', FILENAME = N'C:\mssql\log\out_of_space_log.ldf' , SIZE = 1MB , FILEGROWTH = 4MB , MAXSIZE = 4MB) 
GO 

-- Switch to correct database 
Use [out_of_space]; 
GO 

-- Delete existing schema. 
IF EXISTS (SELECT * FROM sys.schemas WHERE name = N'Temp') 
DROP SCHEMA [Temp] 
GO 

-- Add new schema. 
CREATE SCHEMA [Temp] AUTHORIZATION [dbo] 
GO 

-- Delete existing table 
IF OBJECT_ID(N'[Temp].[PageSplits]') > 0 
    DROP TABLE [Temp].[PageSplits] 
GO 

-- Create new table 
CREATE TABLE [Temp].[PageSplits] 
(
    [SplitId] [int] IDENTITY (1, 1) NOT NULL, 
    [SplitGuid] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWSEQUENTIALID()), 
    [SplitDt] [datetime] NOT NULL DEFAULT (getdate()), 
    CONSTRAINT [pk_Split_Guid] PRIMARY KEY CLUSTERED 
    ([SplitGuid] ASC) 
) 
GO 

-- Make 50K of records 
DECLARE @VAR_CNT INT = 1; 
WHILE (@VAR_CNT <= 50000) 
BEGIN 
    INSERT [Temp].[PageSplits] DEFAULT VALUES; 
    SET @VAR_CNT = @VAR_CNT + 1; 
END 
GO 

-- Get record count 
SELECT COUNT(*) AS TOTAL_RECS 
FROM [Temp].[PageSplits] 
GO 


-- Error Message 

/* 

Msg 1105, Level 17, State 2, Line 5 
Could not allocate space for object 'Temp.PageSplits'.'pk_Split_Guid' in database 'out_of_space' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup. 

*/ 

-- Show me the data file 
sp_spaceused '[Temp].[PageSplits]' 

/* 

name  rows reserved data index_size unused 
PageSplits 46870 1736 KB  1720 KB 16 KB  0 KB 

*/ 

Zasadniczo w pierwszym zbiorze danych podstawowych zabrakło miejsca.

Po dodaniu dodatkowego pliku danych zostanie on automatycznie dodany do podstawowej grupy plików .

-- Add another file 
ALTER DATABASE [out_of_space] 
ADD FILE 
(
    NAME = out_of_space_dat2, 
    FILENAME = N'C:\mssql\data\out_of_space_dat2.ndf', 
    SIZE = 2MB, 
    MAXSIZE = 10MB, 
    FILEGROWTH = 2MB 
); 
GO 


-- Make 5K of records 
DECLARE @VAR_CNT INT = 1; 
WHILE (@VAR_CNT <= 5000) 
BEGIN 
    INSERT [Temp].[PageSplits] DEFAULT VALUES; 
    SET @VAR_CNT = @VAR_CNT + 1; 
END 
GO 

Istnieje wiele sposobów, aby robić takie rzeczy jak wykorzystanie miejsca znalezienia w SQL Server.

Po pierwsze to widoki katalogu . Rozwiązanie Ali nie wyświetla użytych stron, maksymalnych rozmiarów itp.

-- Get allocation units by file and partition 
select 
    OBJECT_NAME(p.object_id) as my_table_name, 
    u.type_desc, 
    f.file_id, 
    f.name, 
    f.physical_name, 
    f.size, 
    f.max_size, 
    f.growth, 
    u.total_pages, 
    u.used_pages, 
    u.data_pages, 
    p.partition_id, 
    p.rows 
from sys.allocation_units u 
    join sys.database_files f on u.data_space_id = f.data_space_id 
    join sys.partitions p on u.container_id = p.hobt_id 
where 
    u.type in (1, 3) and 
    OBJECT_NAME(p.object_id) = 'PageSplits' 
GO 

Moje rozwiązanie podaje te informacje.

enter image description here

Innym sposobem na uzyskanie tych informacji jest z dynamicznych widoków zarządzania.

-- Management view (partitions) 
SELECT * FROM sys.dm_db_partition_stats 
WHERE object_id = OBJECT_ID('Temp.PageSplits'); 
GO 

enter image description here

-- Management view (files) 
SELECT db_name(database_id) as database_nm, * FROM sys.dm_db_file_space_usage 
GO 

enter image description here

Jedynym sposobem, aby odbudować tabeli tak, że jest on jednym pliku jest stworzenie nowej grupy pliku i nowy plik. Upewnij się, że plik jest połączony z nową grupą.

-- Add a new file group 
ALTER DATABASE [out_of_space] 
ADD FILEGROUP fg_new_space 
GO 

-- Add the third data file 
ALTER DATABASE [out_of_space] 
ADD FILE 
(
    NAME = out_of_space_dat3, 
    FILENAME = N'C:\mssql\data\out_of_space_dat3.ndf', 
    SIZE = 2MB, 
    MAXSIZE = 10MB, 
    FILEGROWTH = 2MB 
) 
TO FILEGROUP fg_new_space 
GO 

Upuść wiązanie i przenieś dane do nowej grupy plików. Zbuduj nowy klucz podstawowy, który domyślnie przyjmuje grupę plików tabeli. Właśnie tego chcemy.

-- Drop the constraint 
ALTER TABLE [Temp].[PageSplits] DROP CONSTRAINT [pk_Split_Guid] WITH (MOVE TO [fg_new_space]) 
GO 

-- Add back the primary key 
ALTER TABLE [Temp].[PageSplits] ADD 
CONSTRAINT [pk_Split_Guid] PRIMARY KEY CLUSTERED 
    ([SplitGuid] ASC); 

Ostatni element do uzupełnienia tego artykułu. Możemy uzyskać liczbę miejsc za pomocą SSMS. Przyjrzyjmy się właściwościom tabeli.

enter image description here

Spójrzmy na właściwości indeksu.

enter image description here

Zarówno stół, a indeks klastra są teraz w nowej grupy pliku/plików.

+0

Czy mówisz, że DBCC SHRINKFILE (dbdatafile1, EMPTYFILE) nie przeniesie wszystkich danych do drugiego pliku? – influent

+0

Każda baza danych zawiera 1 * plik .mdf (plik danych podstawowych), 1+ * .ndf (plik danych dodatkowych) i 1+ pliki dziennika * .ldf. Jak stwierdził Microsoft, nie można opróżnić pliku .mdf, ponieważ jest to lokalizacja pliku rozruchowego dla bazy danych z informacjami o systemie. Dlatego nie możesz wykonać tego, co próbujesz. Ponadto, ponieważ WAL - napisz naprzód logowanie jest jednoznaczne, więcej plików * .ldf nie pomaga w wydajności. –

+0

Dzięki, ale pełna odpowiedź. – FLICKER

16

Możesz użyć tego skryptu, aby sprawdzić, które tabele są na jakiej grupy plików i ich rzeczywistej lokalizacji fizycznej

SELECT OBJECT_NAME(i.id) AS [Table_Name] 
     , i.indid 
     , i.[name]   AS [Index_Name] 
     , i.groupid 
     , f.name    AS [File_Group] 
     , d.physical_name AS [File_Name] 
     , s.name    AS [Data_Space] 
FROM  sys.sysindexes i 
INNER JOIN sys.filegroups f  ON f.data_space_id = i.groupid 
            AND f.data_space_id = i.groupid 
INNER JOIN sys.database_files d ON f.data_space_id = d.data_space_id 
INNER JOIN sys.data_spaces s  ON f.data_space_id = s.data_space_id 
WHERE  OBJECTPROPERTY(i.id, 'IsUserTable') = 1 
ORDER BY f.name, OBJECT_NAME(i.id), groupid 
+0

Niesamowity skrypt. +1 –

+1

Co powiecie na pliki danych innych obiektów, takie jak indeksy pełnotekstowe, indeksy nieklastrowe, definicje SP itd.? W jaki sposób można zmodyfikować ten skrypt, aby wyświetlał on wszystkie obiekty w danym db? – Stackoverflowuser

+0

Odpowiedź na pytanie! Dzięki. – FLICKER

Powiązane problemy