데이터베이스를 축소해야합니다-많은 공간을 확보했습니다.


35

이 질문은 여기에서 다양한 형태로 요청되지만 그 질문은 다음과 같이 요약됩니다.

데이터베이스 축소가 위험하다는 것을 알고 있습니다. 이 경우 너무 많은 데이터를 제거했으며 다시는 사용하지 않습니다.

  • 데이터베이스를 축소하는 방법 어떤 파일을 축소합니까?
  • 이 작업을 수행하는 동안 고려해야 할 사항은 무엇입니까?
  • 나중에 무엇을해야합니까?
  • 큰 데이터베이스 인 경우 어떻게합니까? 더 작은 단위로 축소 할 수 있습니까?

2
나는 몇 시간 전에이 고생 : dba.stackexchange.com/questions/47310/... 나는 내 대답에 내 경험을 요약하려고
사바 토스

답변:


30

일부 초기주의 사항 :

  1. 그것은 일반적으로 할 수있는 최악의 사례로 알려져 (로그 파일과 같은 다른 문제가있는 프로덕션 데이터베이스 또는 데이터 파일을 축소 이 질문 에 대해 이야기). 나는 사람들 "적정 규모"와 좋은 계획에 대해 이야기하는 블로그 게시물 에서 데이터베이스를 축소하지 말 것을 권한다 . 나는 혼자가 아닙니다 ( Paul Randal , Brent Ozar , 단지 몇 개의 링크를 더 제공하기 위해). 데이터 파일 또는 데이터베이스 조각 색인을 축소하면 자원이 느리고 힘들고 시스템이 낭비 될 수 있으며 일반적으로 수행하기에는 나쁜 일입니다.
  2. 이 경우, 우리는 모든 위험, 우리가 그것을 다루는이 준비 알지만, 우리는 우리가 많은 공간을 해제 알고 우리가 다시 필요가 없습니다 것입니다. 따라서 이러한 특정 유형의 경우 축소는 우리의 옵션 중 하나로서 의미가 있습니다.

우려와 위험에 대해 읽었으며 상당한 공간을 확보 했기 때문에 여전히 축소를 수행해야하는 경우이 답변의 나머지 부분이 도움이 될 것입니다. 그러나 위험을 고려하십시오.

두 가지 주요 접근 방식이 여기에 있습니다.

1.) 축소 예, 실제 축소를 수행하십시오.DBCC SHRINKFILE 대신 사용 을 고려하십시오 DBCC SHRINKDATABASE. 이로 인해 성능이 약간 저하 수 있습니다. 많은 IO를 수행하는 대규모 작업입니다. 점진적으로 작아지는 대상 크기로 반복 축소하여 잠재적으로 벗어날 수 있습니다 .

위의 DBCC SHRINKFILE링크 에서 "A.)"예입니다.이 예에서 데이터 파일이 7MB 대상 크기로 축소되었습니다. 이 형식은 가동 중지 시간 창에서 허용하는대로 반복적으로 축소하는 좋은 방법입니다. 나는 개발 테스트에서 성능이 어떻게 보이고 얼마나 낮은 / 높이가 증가하는지 그리고 생산의 예상 타이밍을 결정하기 위해 이것을 할 것입니다. 이것은 온라인 작업입니다. 시스템에서 축소 된 데이터베이스에 액세스하는 사용자와 함께 실행할 수 있지만 성능이 저하되어 거의 보장됩니다. 따라서 서버에서 수행중인 작업을 모니터링하고보고 중단 시간 창 또는 더 가벼운 활동 기간을 선택하십시오.

USE YourDatabase;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

항상 기억하십시오 : -축소 할 때마다 인덱스를 조각화하고 장기간에 걸쳐 청크를 축소하려는 경우 인덱스를 다시 작성해야합니다. 한 창에서 모든 작업을 수행 할 수없는 경우 매번 그 비용이 발생합니다.

2) 새 데이터베이스 - 당신은 할 수 여기에 새 데이터베이스 및 마이그레이션 데이터를 생성합니다. 빈 데이터베이스와 모든 키, 인덱스, 개체, 프로세스, 함수 등을 스크립팅 한 다음 데이터를 마이그레이션해야합니다. 이를 위해 스크립트를 작성하거나 Red Gate의 SQL Data Compare와 같은 도구 또는 유사한 도구를 가진 다른 공급 업체를 사용할 수 있습니다. 이것은 사용자 측에서 더 많은 설정 작업, 더 많은 개발 및 테스트이며, 환경에 따라 다운 타임을 줄일 수도 있지만 고려해야 할 옵션이 있습니다.

데이터베이스를 축소 해야 할 때 이것이 내 환경이라면, 디스크 호그 인 것을 좋아하고 미래 / 예기치 않은 성장에 대비하기 위해 데이터 파일에 공평하고 많은 양의 공백을 남기고 싶습니다. 우리는 단지 공간의 대부분을 삭제 한 경우 나는 괜찮주는 공간 돌아올 것입니다,하지만 난 그 말을 "하지만 다시 성장하지 않습니다"아직도 떠나지 신뢰 없었어요 그래서 약간의 공백을. 아마 내가 갈 경로 ( 한숨)은 다운 타임 창이 더 작고 빈 DB를 만들고 데이터를 마이그레이션하는 복잡성을 원치 않는 경우 축소 방식입니다. 나는 그것을 점진적으로 시간의 무리를 축소 할 수 있도록 인덱스를 다시 다음과 (점진적으로 작은 파일 크기를 선택. 내가 dev에 원하는 크기로 내 테스트를 기반으로 필요하다고 생각하는 횟수 기준) .. 그리고 나서 ' d 내 데이터베이스를 축소했다고 말하지 마십시오 ;-)


1
힙에서 (특히 힙 중간에서) 많은 데이터를 삭제하면 클러스터 된 인덱스를 추가 할 때까지 해당 공간을 다시 확보 할 수없는 특별한 경우를 추가 할 것입니다. 그런 다음 클러스터 된 인덱스를 삭제 한 다음 다시 힙으로 바꿉니다. 물론 힙이 정기적으로 잘 리면 걱정할 필요가 없습니다. 그러나 여전히 언급 할 가치가 있습니다.
Jonathan Fite

누군가가 NOTRUNCATE 및 TRUNCATEONLY의 의미를 설명 할 수 있습니까? 후자는 페이지를 다시 정렬하지 않으므로 인덱스 조각화가 발생하지 않습니까?
David Garcia

4
  1. 데이터베이스를 축소하는 방법 어떤 파일을 축소합니까? : DBCC SHRINKFILE언급 한 명령으로 파일을 개별적으로 축소 할 수 있습니다 . 데이터베이스가 구성하는 파일 수는 서버에 따라 다릅니다. 단순 데이터베이스에는 하나의 데이터베이스 파일과 하나의 트랜잭션 로그 파일이 있습니다.
  2. 이 작업을 수행하는 동안 고려해야 할 사항은 무엇입니까?: 축소는 인덱스 조각화에 영향을 미칩니다 (3 단계 참조). 또한 실제 환경에서는 어쨌든 커질 수 있으므로 데이터베이스 파일을 가능한 최소한의 크기로 축소하고 싶지는 않습니다. 따라서 프로덕션 환경에서 채워지기 때문에 데이터베이스 파일 내에 10 % -20 %의 여유 공간을 남겨 두는 방식으로 크기 (예 : 7MB)를 조정하려고합니다. 자동 성장주기를 절약하십시오. 따라서 실제 숫자는 신중하게 계산해야합니다. 또한 수행 한 "큰 공간 확보"는 DB 파일 내에서 확보 한 공간보다 트랜잭션 로그 파일을 크게 증가시킵니다. 또한, 실제 경험할 수있는 공간 이득은 수학적으로 예상되는 것보다 적습니다! 수학적으로 12 기가를 풀 었다고 가정 해 봅시다.
  3. 나중에 무엇을해야합니까? : 앞에서 언급했듯이 SHRINK의 변경으로 인해 조각화가 왜곡 된 인덱스를 다시 색인화하려고합니다. 쿼리 통계에 대해 특별한 조치가 필요한 경우 충분히 실험하지 않았습니다.
  4. 큰 데이터베이스 인 경우 어떻게합니까? 더 작은 단위로 축소 할 수 있습니까? SHRINK 작업은 언제든지 중단 될 수 있으며 나중에 계속 진행할 수 있습니다. 가능하면 오프라인 데이터베이스에서 수행하는 것이 좋습니다. 그래도 중단하고 계속 설정하면 동일한 축소 크기로 진행됩니다. 이론적으로 7MB 대신 덜 단단한 대상 크기를 지정하여 더 작은 단위로 축소 할 수 있지만 프로덕션 환경에서 수행하는 경우 한 번만 제공한다고 말하고 싶습니다. 보시다시피 인덱스 조각화 및 가능한 트랜잭션 로그 증가에 문제가 있습니다. 한 번만하겠습니다.

어쨌든 SHRINK를 정기적으로 수행하지 않는 것이 좋습니다. 어쨌든 당신이 아마 알고있는 모든 경고와 면책 조항을 없애려고 노력합니다. 백업하고 가능하면 집에서하지 마십시오 :)

보너스 : 복제 환경에서 게시자 데이터베이스에서이 작업을 수행하면 구독자 데이터베이스가 축소되지 않습니다 (Express 버전이므로 크기 문제가있을 수 있음).

마지막으로, 재색 인 스크립트 :

USE YourDBName

DECLARE @TbName VARCHAR(255)
DECLARE @FullTbName VARCHAR(255)
DECLARE @IxName VARCHAR(255)
DECLARE myCursor CURSOR FOR
    SELECT OBJECT_NAME(dmi.object_id) AS TableName,i.name AS IndexName
    FROM sys.dm_db_index_physical_stats(14, NULL, NULL, NULL , 'LIMITED') dmi
    JOIN  sys.indexes i on dmi.object_id = i.object_id and dmi.index_id = i.index_id
    WHERE avg_fragmentation_in_percent > 30
    ORDER BY avg_fragmentation_in_percent
OPEN myCursor
FETCH NEXT FROM myCursor INTO @TbName, @ixName
WHILE @@FETCH_STATUS = 0
BEGIN
    IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'dba' AND TABLE_NAME = @TbName)
BEGIN
        SET @FullTbName = 'dba.' + @TbName
        IF (@ixName IS NULL)
        BEGIN
            PRINT 'Reindexing Table ' + @FullTbName
            DBCC DBREINDEX(@FullTbName, '', 0)
        END
        ELSE
        BEGIN
             PRINT 'Reindexing Table ' + @FullTbName + ', Index ' + @IxName
             DBCC DBREINDEX(@FullTbName, @IxName, 0)
        END
    END
    FETCH NEXT FROM myCursor INTO @TbName, @ixName
END
CLOSE myCursor
DEALLOCATE myCursor

여기서 유일한 변수는 14이며 select를 실행하여 얻을 수 있으며 DB_ID('YourDBName')스크립트는 dba. * 스키마의 테이블에만 관심이 있다고 가정합니다.


2
인덱스 재 빌드의 경우 DBREINDEX는 SQL 2005에서 더 이상 사용되지 않습니다. 커서가있는 거대한 스크립트 대신 다음을 사용할 수 있습니다. EXEC sp_MSForeachtable @ Command1 = "ALTER INDEX ALL ON? REBUILD"누군가에게 도움이되기를 바랍니다.
KISS

2

데이터베이스 축소에 대한 모든 경고를 들었으며 모두 사실입니다. 인덱스를 조각화하고 일반적으로 데이터베이스를 정리하여 프로덕션 시스템에서 수행해서는 안됩니다.

그러나 SSD 드라이브의 공간으로 인해 워크 스테이션에서 백업을 복원 할 때 일반적으로 주 단위로 수행합니다. 이 스크립트를 쓰지 않았지만 몇 년 전에 찾았습니다. 다른 데이터베이스 (250GB)에서 필자는 필요한 테이블을 전송 한 다음 인덱스 인덱스를 새로 생성하는 SSIS 패키지를 만들었습니다.

DECLARE @DBFileName SYSNAME

DECLARE @TargetFreeMB INT

DECLARE @ShrinkIncrementMB INT

SET @DBFileName = 'Set Name of Database file to shrink'

-- Set Desired file free space in MB after shrink

SET @TargetFreeMB = 500
-- Set Increment to shrink file by in MB
SET @ShrinkIncrementMB = 100

SELECT [FileSizeMB] = convert(NUMERIC(10, 2),
round(a.size / 128., 2)),

[UsedSpaceMB] = convert(NUMERIC(10, 2),

round(fileproperty(a.NAME, 'SpaceUsed') / 128., 2)),

[UnusedSpaceMB] = convert(NUMERIC(10, 2),

round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2)),

[DBFileName] = a.NAME

FROM sysfiles a

DECLARE @sql VARCHAR(8000)
DECLARE @SizeMB INT
DECLARE @UsedMB INT

SELECT @SizeMB = size / 128.
FROM sysfiles
WHERE NAME = @DBFileName

SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

SELECT [StartFileSize] = @SizeMB
    ,[StartUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

WHILE @SizeMB > @UsedMB + @TargetFreeMB + @ShrinkIncrementMB

BEGIN
    SET @sql = 'dbcc shrinkfile ( ' + @DBFileName + ', ' + convert(VARCHAR(20), @SizeMB - @ShrinkIncrementMB) + ' ) '

    PRINT 'Start ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    EXEC (@sql)

    PRINT 'Done ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    SELECT @SizeMB = size / 128.
    FROM sysfiles
    WHERE NAME = @DBFileName

    SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

    SELECT [FileSize] = @SizeMB
        ,[UsedSpace] = @UsedMB
        ,[DBFileName] = @DBFileName
END

SELECT [EndFileSize] = @SizeMB
    ,[EndUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

SELECT [FileSizeMB] = convert(NUMERIC(10, 2), round(a.size / 128., 2))

    ,[UsedSpaceMB] = convert(NUMERIC(10, 2), round(fileproperty a.NAME, 'SpaceUsed') / 128., 2))

,[UnusedSpaceMB] = convert(NUMERIC(10, 2), round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2))

,[DBFileName] = a.NAME

FROM sysfiles a

1

아래 인용문은 Microsoft에서 직접 제공 한 것으로 (버전 2008-2016에 적용), 언제 / 언제, DBCC SHRINKFILE명령 사용 방법에 대한 지침을 제공합니다 .

https://msdn.microsoft.com/en-us/library/ms189493.aspx

모범 사례

파일을 축소 할 때는 다음 정보를 고려하십시오.

  • 축소 작업은 자르기 테이블 또는 테이블 삭제 작업과 같이 사용하지 않는 공간을 많이 만드는 작업 후에 가장 효과적입니다.
  • 대부분의 데이터베이스는 일상적인 작업에 사용 가능한 여유 공간이 필요합니다. 데이터베이스를 반복적으로 축소하고 데이터베이스 크기가 다시 커지면 일반 작업에 줄어든 공간이 필요함을 나타냅니다. 이 경우 데이터베이스를 반복적으로 축소하는 것은 낭비되는 작업입니다.
  • 축소 작업은 데이터베이스에서 인덱스의 조각화 상태를 유지하지 않으며 일반적으로 조각화를 어느 정도 증가시킵니다. 이것이 데이터베이스를 반복적으로 축소하지 않는 또 다른 이유입니다.
  • 동일한 데이터베이스에서 여러 파일을 동시에 대신에 축소합니다. 시스템 테이블의 경합으로 인해 차단으로 인해 지연이 발생할 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.