SQL Server(この場合は2008)で、インスタンス上のすべてのデータベースのすべてのファイル(ログとデータの両方)をすばやく縮小するにはどうすればよいですか? SSMSを実行し、それぞれを右クリックして[タスク]-> [縮小]を選択することもできますが、もっと速いものを探しています。
私はいくつかの「データベース作成」スクリプトをスクリプト化しましたが、それらがデフォルトの膨らんだサイズであることを忘れており、このプロジェクトでこれらのファイル用に予約されているスペースをそれほど必要としません。
GUIから「タスク->縮小」を実行すると、実際にはDBCC SHRINKDATABASE
コマンドを裏で実行します。それを試してみてください。ダイアログボックスが表示されたら、「OK」ボタンをクリックしないでください。代わりに、「スクリプト」ボタンをクリックしてください。クエリウィンドウにコマンドが表示されます。これを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行のSQL文はどうですか?
次のSQLステートメントを実行する前に、 this 非常に興味深いブログ投稿をお読みください。
EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'
DBCC SHRINKDB(およびその従兄弟のSHRINKFILE)は、そのコードで実行されているシングルスレッドの実行が多いため、非常に低速です。
データベースファイルを縮小するはるかに高速な方法は次のとおりです。
sp_spaceused
を使用して、サイズを決定します)インデックスの再構築は大規模な並列処理であるため、この手法を使用すると、データベースの圧縮がはるかに高速になります。もちろん、プロセスが進行している間、新しいファイルグループ用に少し余分なスペースが必要になります。ただし、新しいファイルグループに必要なのは、インスタンス内で最大のファイルグループを保持するのに十分なスペースだけです(作業を進めるにつれてスペースを再利用するため)。
この手法には、プロセスでインデックスを最適化するという追加の利点もあります。
要求に応じてLOGのみを縮小するようにクエリを少し調整しました。
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'
以下のコードは、非システムデータベースのリストを取得し、データベースを読み取り専用に設定して、ファイルを圧縮します。スペースが常に問題となるSQLエージェントジョブを使用して、このコードをいくつかのSQL Serverボックスに保存しました。毎週土曜と日曜の夜に、実行が開始され、すべてのデータベースが数時間以内に縮小されます(データベースのサイズによって異なります)。
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
これは上記の答えを拡張し、カーソルを使用してSQLステートメントを1つずつ繰り返します。 Emrahの答えほど短くはありませんが、カーソル内のwhileループ内で追加のロジックを使用できます。
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
マスター、モデル、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'
すべてのデータベースに対して動的に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
詳細は この記事 にあります。