it-swarm.dev

Jak szybko zmniejszyć wszystkie pliki dla wszystkich baz danych?

Jak w programie SQL Server (w tym przypadku w 2008 r.) Mogę szybko zmniejszyć wszystkie pliki, zarówno dziennik, jak i dane, dla wszystkich baz danych w instancji? Mógłbym przejść przez SSMS i kliknąć każdy z nich prawym przyciskiem myszy i wybrać Zadania -> Zmniejsz, ale szukam czegoś szybszego.

Skrypty wykonałem kilka skryptów „Utwórz bazę danych” i zapomniałem, że miały one domyślne rozmiary w dymkach i nie potrzebuję tyle miejsca zarezerwowanego dla tych plików w tym projekcie.

47
jcolebrand

Gdy wykonasz „Zadania -> Zmniejsz” z GUI, faktycznie wydaje DBCC SHRINKDATABASE polecenie za kulisami. Spróbuj. Kiedy pojawi się okno dialogowe, nie klikaj przycisku „OK”. Zamiast tego kliknij przycisk „Skrypt”. Zobaczysz polecenie w oknie zapytania. Połącz to z zapytaniem w sys.databases (pomiń master i msdb), a możesz stworzyć skrypt, aby zmniejszyć wszystkie bazy danych.

Na przykład (wzięty z komentarza jcolebrand):

SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4;

Skopiuj dane wyjściowe tego zapytania i uruchom je, aby zmniejszyć wszystkie pliki.

59
Larry Coleman

Co powiesz na jedną linię instrukcji SQL?

Przeczytaj ten bardzo interesujący post na blogu przed wykonaniem poniższej instrukcji sql.

EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'
22
CoderHawk

DBCC SHRINKDB (i jego kuzyn SHRINKFILE) są bardzo powolne, ponieważ w tym kodzie dzieje się wiele pojedynczych wątków.

Znacznie szybszy sposób zmniejszenia pliku bazy danych jest następujący:

  • Przydziel nową grupa plików do bazy danych
  • Ustaw tę grupa plików tak dużą, jak musi być (użyj sp_spaceused, aby określić, jak duże)
  • Odbuduj wszystkie indeksy do tej nowej grupy plików
  • Upuść starą aplikację

Ponieważ przebudowy indeksu są masowo równoległe, ta technika często powoduje znacznie szybsze zmniejszanie bazy danych. Oczywiście wymaga to trochę dodatkowej przestrzeni dla nowej grupy plików podczas trwania procesu. Jednak potrzebna jest tylko wystarczająca ilość miejsca w nowej grupie plików, aby pomieścić największą grupę plików w instancji (ponieważ będziesz zbierać przestrzeń w miarę postępów).

Ta technika ma również dodatkową zaletę defragmentacji indeksów w tym procesie.

15
Thomas Kejser

Zoptymalizowałem trochę zapytanie, aby zmniejszyć tylko LOG, zgodnie z żądaniem:

set nocount on  
SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4 and mf.type_desc = 'LOG'
13
Frankachela

Poniższy kod, pobierz listę niesystemowych baz danych, ustaw bazę danych tylko do odczytu, a następnie zmniejsz plik. Trzymam ten kod w kilku polach programu SQL Server za pomocą SQL Agent Job, gdzie zawsze jest miejsce. W soboty i niedziele co tydzień zaczyna się uruchamiać i zmniejszać wszystkie bazy danych w ciągu kilku godzin (w zależności od wielkości baz danych).

declare @db varchar(255)
declare c cursor for
select name from sys.databases where is_read_only=0 and state=0
  and name not in ('master','model','tempdb','msdb')
open c
fetch c into @db
while @@fetch_status=0
begin
  exec SP_dboption @db,'trunc. log on chkpt.','true' 
  DBCC shrinkdatabase (@db)
  fetch next from c into @db
end
close c
deallocate c

Ten rozszerza powyższą odpowiedź, używając kursora do iteracji kolejno instrukcji SQL. Nie jest tak krótki jak odpowiedź Emrah'a, ale pozwala na dodatkową logikę w pętli while w obrębie kursora.

SELECT 
    'USE [' 
    + databases.name + N']' 
    + CHAR(13) 
    + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' 
    + masterFiles.name 
    + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) 
    + CHAR(10) 
    + CHAR(13) 
    + CHAR(10)                                                                  AS sqlCommand
INTO
    #shrinkCommands
FROM 
    [sys].[master_files] masterFiles 
    INNER JOIN [sys].[databases] databases ON masterFiles.database_id = databases.database_id 
WHERE 
    databases.database_id > 4; -- Exclude system DBs


DECLARE iterationCursor CURSOR

FOR
    SELECT 
        sqlCommand 
    FROM 
        #shrinkCommands

OPEN iterationCursor

DECLARE @sqlStatement varchar(max)

FETCH NEXT FROM iterationCursor INTO @sqlStatement

WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC(@sqlStatement)
    FETCH NEXT FROM iterationCursor INTO @sqlStatement
END

-- Clean up
CLOSE iterationCursor
DEALLOCATE iterationCursor
DROP TABLE #shrinkCommands
0
Alistair

Zmniejsz wszystkie pliki dziennika oprócz głównego, modelu, msdb:

EXEC sp_MSforeachdb '
DECLARE @sqlcommand nvarchar (500)
IF ''?'' NOT IN (''master'', ''model'', ''msdb'')
BEGIN
USE [?]
SELECT @sqlcommand = ''DBCC SHRINKFILE (N'''''' + 
name
FROM [sys].[database_files]
WHERE type_desc = ''LOG''
SELECT @sqlcommand = @sqlcommand + '''''' , 0)''
EXEC sp_executesql @sqlcommand
END'
0
Emrah Saglam

Możemy powtarzać SHRINKDB i SHRINKFILE dla wszystkich baz danych dynamicznie:

while @DBID<[email protected]
begin
  -- Used Dynamic SQL for all databases.
  Set @SQL ='Use '[email protected]+ ' '+Char(10)
  Set @SQL += 'DBCC SHRINKFILE('[email protected]+',5)' +Char(10)
  Set @SQL += 'DBCC SHRINKDATABASE('[email protected]+')'+Char(10)

  --#6 Increment DBid for looping over all databases
  Set @DBID = @DBID+1
  Select @DBName = DBName, @Filename=DBFileName from #DBNames where [dbid] = @DBID and type_Desc = 'LOG'
  Print (@SQL)
  Exec (@SQL)
end

Szczegółowe informacje można znaleźć w w tym artykule .

0
Anup Kulkarni