最近、本番データベースから古いデータを消去しました。データベースは3 TB with 1.4 TB emptyですが、6〜8個のデータベースを使用してスペースを利用していないため、開発とQAインスタンスに問題が発生します。 1.4 TB空のスペース、特に開発時にスペースの制約がある場合。以下のコードを使用して開発データベースを縮小するジョブをセットアップしたい
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (''?'' , 10)'
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (''?'' , 0, TRUNCATEONLY)'
「sys.database_filesでデータベース 'Test'のファイル 'Test'を見つけることができませんでした。ファイルが存在しないか、削除されました。」というエラーが発生します。データベースには複数のデータファイルがあります。複数のデータファイルに対応できるようにコードを改善するにはどうすればよいですか。
@sp_BlitzErikは問題を正しく識別していますが、別の解決策を提案します:createsSHRINKFILE
ステートメントを1回限りのスクリプトで使用し、正常性を確認してから手動で実行するか、エージェントジョブ:
SELECT dbname = DB_NAME(),
file_name = name,
TotalMB = CONVERT(decimal(12,1),size/128.0),
UsedMB = CONVERT(decimal(12,1),FILEPROPERTY(name,'SpaceUsed')/128.0),
FreeMB = CONVERT(decimal(12,1),(size - FILEPROPERTY(name,'SpaceUsed'))/128.0),
Command = CONCAT('USE ', DB_NAME(), '; DBCC SHRINKFILE (name = ',
[name], ', size = ',
convert(int,round(1.15 * FILEPROPERTY(name,'SpaceUsed')/128,-1)), 'MB)')
FROM sys.database_files WITH (NOLOCK)
WHERE type_desc = 'ROWS'
ORDER BY file_id;
これを各データベースから1回実行すると、各データファイルの合計および使用済みサイズが返されます(ログファイルはスキップされ、後で手作業で即座に縮小できます)、およびSHRINKFILE
ステートメントの例現在使用されているスペースから計算された、ファイル内の15%の空きスペースの目標:
USE myDB; DBCC SHRINKFILE (name = myDBData, size = 148910MB)
ファイルalreadyの空き領域が15%未満の場合は、結果の健全性を確認する必要があります。その場合、SHRINKFILE
ステートメントは現在のサイズよりも大きいサイズを指定するため、スキップします(すでに小さい)足りる)。
すべてのデータファイルを縮小したら、各logファイルのターゲットサイズを選択し(通常、データファイルサイズの10〜25%を使用します)、手動で縮小します。これは、復旧モデルと、これらのデータベースがその環境で取得するアクティビティの量によって異なる場合があります。
疑問符は、縮小しようとしているファイル名ではなく、データベース名に評価されます。
例えば:
EXEC master.sys.sp_MSforeachdb ' USE [?]; PRINT N''?''; ';
戻ります(私のサーバー上)
master
tempdb
model
msdb
SUPERUSER
StackOverflow
StackOverflow_CS
Crap
DBAtools
StackOverflow2010
SUPERUSER_CX
ಠ_ಠ
StackOverflow2010ಠ_ಠ
DBCC SHRINKFILE はそれを引数として取りません:
DBCC SHRINKFILE(
{file_name | file_id}
{[、EMPTYFILE]
| [[、target_size] [、{NOTRUNCATE |切り捨て}]]
})[WITH NO_INFOMSGS付き]
.mdfと.ldfしかない場合は、(間違いではありませんが)コードを次のように置き換えることができます。
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (1 , 10)'
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (2 , 0, TRUNCATEONLY)'
ファイルIDなどを検索するためのより詳細なコードは、読者への課題として残されています。
全体を縮小したい場合は、代わりに DBCC SHRINKDATABASE を使用します。これはデータベース名を取り、元のコードで動作します。
DBCC SHRINKDATABASE(database_name | database_id | 0
[、target_percent]
[、{NOTRUNCATE | TRUNCATEONLY}])[NO_INFOMSGS付き]
もちろん、これは あらゆる種類の問題 を引き起こす可能性があり、私はそれをしたくありません。
@BradCこれは私があなたの提案されたコードをどのように適応させたかです
CREATE TABLE #ShrinkFile
(
DBName sysname,
File_Name sysname,
TotalMB decimal (18,2),
UsedMB decimal (18,2),
FreeMB decimal (18,2),
Command nvarchar(MAX)
)
EXEC master.sys.sp_MSforeachdb ' USE [?];
Insert Into #ShrinkFile (DBName, File_Name, TotalMB, UsedMB, FreeMB,
Command)
SELECT dbname = DB_NAME(),
file_name = name,
TotalMB = CONVERT(decimal(12,1),size/128.0),
UsedMB = CONVERT(decimal(12,1),FILEPROPERTY(name,''SpaceUsed'')/128.0),
FreeMB = CONVERT(decimal(12,1),(size -
FILEPROPERTY(name,''SpaceUsed''))/128.0),
Command = CONCAT(''USE '', DB_NAME(), ''; DBCC SHRINKFILE (name = '',
[name], '', size = '',
convert(int,round(1.15 *
FILEPROPERTY(name,''SpaceUsed'')/128,-1)), ''MB)'')
FROM sys.database_files WITH (NOLOCK)
WHERE type_desc = ''ROWS''
ORDER BY file_id;'
IF EXISTS (SELECT * FROM #ShrinkFile WHERE FreeMB > 1000)
BEGIN
DECLARE @SQLText nvarchar(max)
DECLARE Shrink_cursor CURSOR FOR
SELECT DISTINCT Command FROM #ShrinkFile
WHERE FreeMB > 1000
OPEN Shrink_cursor
FETCH NEXT FROM Shrink_cursor INTO @SQLText
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC (@SQLText)
FETCH NEXT FROM Shrink_cursor INTO @SQLText
END
CLOSE Shrink_cursor
DEALLOCATE Shrink_cursor
END
DROP TABLE #ShrinkFile