모든 데이터베이스의 모든 파일을 빠르게 축소하려면 어떻게합니까?


47

SQL Server (2008의 경우)에서 인스턴스의 모든 데이터베이스에 대한 모든 파일 (로그 및 데이터)을 빠르게 축소하려면 어떻게해야합니까? SSMS를 통해 마우스 오른쪽 버튼을 클릭하고 작업-> 축소를 선택할 수 있지만 더 빠른 것을 찾고 있습니다.

나는 "데이터베이스 생성"스크립트를 스크립팅하고 기본값으로 풍선 크기를 가지고 있다는 것을 잊어 버렸고이 프로젝트에서 이러한 파일을 위해 예약 된 공간이 많이 필요하지 않습니다.

답변:


55

GUI에서 "작업-> 축소"를 수행하면 실제로 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

진심으로. @Sandy의 답변을 확인하십시오. sp_MSForEachDB ( "테이블"단계도 있음)는 매우 유용합니다
swasheck

3
그리고이 글을 읽는 모든 사람들에게 꼭 상기해야 할 것이 있습니다 : 데이터베이스 축소는 위험합니다.
Nick Chammas

1
오프라인 DB를 필터링하면 더 좋을 것입니다. :-)
TiloBunt

1
@TiloBunt와 동의하면 d.database_id> 4 AND d.state_desc = 'ONLINE';
Mauro

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/…
Aaron Bertrand

15

DBCC SHRINKDB (및 사촌 SHRINKFILE)는 해당 코드에서 많은 단일 스레드 실행이 진행되므로 매우 느립니다.

데이터베이스 파일을 축소하는 훨씬 빠른 방법은 다음과 같습니다.

  • 새 파일 그룹을 데이터베이스에 할당
  • 이 파일 그룹을 필요한만큼 크게 만드십시오 ( sp_spaceused얼마나 큰지를 결정 하는 데 사용 )
  • 이 새 파일 그룹에 대한 모든 인덱스를 다시 작성하십시오.
  • 기존 파일 그룹 삭제

인덱스 재 구축은 대규모 병렬이기 때문에이 기술을 사용하면 데이터베이스가 훨씬 더 빨리 축소됩니다. 물론 프로세스가 진행되는 동안 새 파일 그룹을위한 약간의 추가 공간이 필요합니다. 그러나 새 파일 그룹에는 인스턴스에서 가장 큰 파일 그룹을 보유하기에 충분한 공간 만 있으면됩니다 (공간을 확보 할 때마다).

이 기술은 또한 프로세스에서 인덱스 조각 모음을 수행 할 수 있다는 이점이 있습니다.


중요한 부분을 잊었습니다. 인덱스를 다시 작성해도 저장 프로 시저, 뷰, 함수, 동의어, 힙 등과 같은 항목은 이동하지 않습니다.
Jeff Moden

그리고 그것들은 당신이 신경 써야 할 공간을 차지하지 않습니다. 그들은 PRIMARY 파일 그룹에도 상주해야합니다. 실제로 이동할 수 없습니다 (또는 둘 다)
Thomas Kejser

13

요청이있을 때 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'

"모든 파일, 로그 및 데이터를 신속하게 축소"
dezso

2
나는 이것을 찾고 있었고 당신의 대답을 보았을 때 두 배의 게시물을 올리려고했습니다. 직접적인 답변은 아니지만 매우 관련성이 있으며 제 사건에 주목하십시오.
Gomibushi

2

아래 코드는 비 시스템 데이터베이스 목록을 가져 와서 데이터베이스를 읽기 전용으로 설정 한 다음 파일을 축소합니다. 공간이 항상 문제가되는 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

0

master, model, 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 문을 하나씩 반복하여 위의 대답을 확장합니다. 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

0

우리는 반복 할 수 있습니다 SHRINKDBSHRINKFILE동적으로 모든 데이터베이스에 대해 :

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

이 기사 에서 세부 사항을 찾을 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.