Як швидко зменшити всі файли для всіх баз даних?


47

Як у SQL Server (у даному випадку 2008) можна швидко зменшити всі файли, як журнал, так і дані для всіх баз даних в екземплярі? Я міг пройти SSMS і клацнути правою кнопкою миші кожну та вибрати завдання -> Зменшити, але я шукаю щось швидше.

Я написав декілька сценаріїв "Створити базу даних" і забув, що вони мають розміри на кулі для значень за замовчуванням, і мені не потрібно дуже багато місця, відведеного для цих файлів у цьому проекті.

Відповіді:


55

Коли ви робите "Завдання -> Стискати" з графічного інтерфейсу, він фактично видає DBCC SHRINKDATABASEкоманду за кадром. Спробуй це. Коли з'явиться діалогове вікно, не натискайте кнопку "ОК". Замість цього натисніть кнопку "Сценарій". Ви побачите команду у вікні запиту. Поєднайте це із запитом на sys.databases (залиште master та msdb), і ви можете створити сценарій, щоб зменшити всі бази даних.

Наприклад (взяті з коментаря 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;

Скопіюйте вихід цього запиту та запустіть його, щоб зменшити всі ваші файли.


1
Гаразд, я думаю, що у мене є те, що я хочу (потворно, але робить саме те, що мені потрібно), 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але з'ясування цього поставило мені нову проблему. Вимкнути, щоб написати ще одне питання.
jcolebrand

Серйозно. Перевірте відповідь @ Сенді. sp_MSForEachDB (є також проросток "таблиці" теж є дуже корисним
swasheck

3
І ось обов’язкове нагадування для всіх, хто це читає: Скорочення бази даних небезпечно.
Нік Чаммас

1
відфільтрувати офлайн БД зробить це ще краще. :-)
TiloBunt

1
Погоджено з @TiloBunt, вся умова краща як WHERE d.database_id> 4 AND d.state_desc = 'ONLINE';
Мауро

23

Як щодо одного рядка заяви sql?

Будь ласка, прочитайте цю дуже цікаву публікацію в блозі, перш ніж виконати наступне твердження sql.

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

6
Один рядок коду не обов'язково краще, якщо він може працювати неправильно. Будь ласка, також прочитайте ці повідомлення, оскільки sp_msforeachdb може пропустити бази даних і не попередити вас: sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… та mssqltips.com/sqlservertip/2201/…
Аарон Бертран

15

DBCC SHRINKDB (і його двоюрідний брат SHRINKFILE) надзвичайно повільні, тому що в цьому коді відбувається багато однопоточного виконання.

Набагато швидший спосіб зменшити файл бази даних:

  • Виділіть нову групу файлів до бази даних
  • Зробіть групу файлів такою великою, якою вона має бути (використовуйте, sp_spaceusedщоб визначити, наскільки велика)
  • Перебудуйте всі індекси до цієї нової групи файлів
  • Видаліть стару групу файлів

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

Ця методика також має додаткову перевагу дефрагментації ваших індексів у процесі.


Ви забули важливу частину. Перебудова індексів не перемістить нічого іншого, включаючи збережені процедури, перегляди, функції, синоніми, купи тощо,
Jeff Moden

І вони не займають місця, яке вам повинно бути турботою. Вони також мають проживати у групі
ПЕРВІНЬОГО файлу

13

Я трохи налаштував запит, щоб зменшити лише ЛОГІЙ, як це вимагається:

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'

"швидко зменшити всі файли, і журнал, і дані"
дез

2
Я шукав це, і вже збирався подвоїти повідомлення, коли побачив вашу відповідь. Не пряма відповідь, але ДУЖЕ актуально та місце для моєї справи.
Гомібуші

2

У наведеному нижче коді отримайте список несистемних баз даних, встановіть базу даних лише для читання, а потім зменшіть файл. Я зберігав цей код у кількох скриньках SQL Server із використанням роботи SQL Agent Job, де простір - це завжди проблема. У ніч на Сб / Сон щотижня він починає працювати і скорочувати всі бази даних протягом декількох годин (залежно від розміру баз даних).

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

0

Зменшити всі файли журналу, крім головного, моделі, 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

Цей варіант розширює відповідь вище, використовуючи курсор для повторення через оператори SQL по черзі. Це не так коротко, як відповідь Емри, але він дозволяє додатковою логікою знаходитись в циклі "час" всередині курсору.

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

Ми можемо динамічно повторювати SHRINKDBта SHRINKFILEдля всіх баз даних:

while @DBID<=@MaxDBID
begin
  -- Used Dynamic SQL for all databases.
  Set @SQL ='Use '+@DBName+ ' '+Char(10)
  Set @SQL += 'DBCC SHRINKFILE('+@Filename+',5)' +Char(10)
  Set @SQL += 'DBCC SHRINKDATABASE('+@DBName+')'+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

Деталі ви можете знайти в цій статті .

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