top of page

🚀 Shrink de Datafiles no SQL Server: Redução Controlada em Lotes com Monitoramento em Tempo Real

Quem administra bancos de dados SQL Server sabe que executar um simples DBCC SHRINKFILE em arquivos gigantescos pode ser uma verdadeira dor de cabeça. Fazer essa redução de uma vez só costuma gerar problemas severos de concorrência e uma sobrecarga brutal de I/O (leitura e gravação no disco), o que pode acabar travando a sua aplicação.

Para resolver esse problema, a melhor estratégia é "fatiar" essa tarefa. Disponibilizamos abaixo um pacote de scripts para você realizar o shrink de forma inteligente, segura e monitorada.

🌟 O Diferencial do Nosso Script

Em vez de usar a abordagem tradicional, onde o DBA precisa calcular e "adivinhar" o tamanho final ideal do arquivo, nosso script inverte a lógica para facilitar a sua vida:

  • Foco na Redução: Você informa apenas quantos Megabytes deseja liberar. O script calcula o resto.

  • Trava de Segurança: O código lê o espaço real ocupado pelos dados. Se você pedir para reduzir 50 GB, mas houver apenas 10 GB livres, a meta é ajustada automaticamente para não interromper ou corromper a base.

  • Pausas Estratégicas (I/O): A redução é feita em pequenos lotes (chunks de 2 GB). Entre cada lote, o script pausa por 5 segundos, dando um "respiro" para o disco do servidor.

🛠️ Script 1: Executando o Shrink Inteligente

Atenção: Antes de executar, lembre-se de substituir as marcações genéricas [NOMEDOBANCO] e N'NOMEDODATAFILE' pelo nome do seu banco e pelo nome lógico do seu datafile, respectivamente.

SQL

USE [NOMEDOBANCO];
GO

DECLARE @FileName SYSNAME = N'NOMEDODATAFILE'; -- Nome do datafile a ser feito o shrink
DECLARE @ReduceMB INT = 50000;      -- Quantidade em MB para reduzir (Ex: 50000). Coloque 0 para limpar tudo.
DECLARE @ChunkMB INT = 2048;        -- Reduzir de 2048 em 2048 MB (2 GB por vez)

DECLARE @InitialSizeMB INT;
DECLARE @UsedSpaceMB INT;
DECLARE @TargetSizeMB INT;
DECLARE @CurrentSizeMB INT;
DECLARE @TotalSteps INT;
DECLARE @CurrentStep INT = 1;
DECLARE @Message NVARCHAR(2048);

-- 1. Obtém o tamanho inicial em MB
SELECT @InitialSizeMB = size * 8 / 1024 
FROM sys.database_files 
WHERE name = @FileName;

-- Validação de Nome Lógico
IF @InitialSizeMB IS NULL
BEGIN
    RAISERROR('ERRO FATAL: O arquivo lógico "%s" não foi encontrado. Verifique o nome correto usando sp_helpfile.', 16, 1, @FileName) WITH NOWAIT;
    RETURN; -- Aborta o script
END

-- 2. Obtém o espaço real utilizado pelos dados no arquivo (em MB)
SET @UsedSpaceMB = CAST(FILEPROPERTY(@FileName, 'SpaceUsed') AS INT) * 8 / 1024;

-- 3. Define a meta de tamanho
IF @ReduceMB = 0
BEGIN
    SET @TargetSizeMB = @UsedSpaceMB;
    SET @Message = FORMATMESSAGE('Modo TRUNCATE ativado. O alvo será o tamanho mínimo possível: %d MB.', @TargetSizeMB);
    RAISERROR(@Message, 10, 1) WITH NOWAIT;
END
ELSE
BEGIN
    SET @TargetSizeMB = @InitialSizeMB - @ReduceMB;
    
    -- Trava de segurança
    IF @TargetSizeMB < @UsedSpaceMB
    BEGIN
        SET @TargetSizeMB = @UsedSpaceMB;
        RAISERROR('ATENÇÃO: A redução solicitada é maior que o espaço livre! Ajustando a meta para proteger os dados.', 10, 1) WITH NOWAIT;
    END
END

-- ==========================================
-- PAINEL DE DIAGNÓSTICO (Mostra na tela)
-- ==========================================
RAISERROR('--------------------------------------------------', 10, 1) WITH NOWAIT;
SET @Message = FORMATMESSAGE('Tamanho Atual do Arquivo : %d MB', @InitialSizeMB);
RAISERROR(@Message, 10, 1) WITH NOWAIT;
SET @Message = FORMATMESSAGE('Espaço Ocupado por Dados : %d MB (Não pode ser reduzido além disso)', @UsedSpaceMB);
RAISERROR(@Message, 10, 1) WITH NOWAIT;
SET @Message = FORMATMESSAGE('Meta Final do Shrink     : %d MB', @TargetSizeMB);
RAISERROR(@Message, 10, 1) WITH NOWAIT;
RAISERROR('--------------------------------------------------', 10, 1) WITH NOWAIT;

SET @CurrentSizeMB = @InitialSizeMB;

-- 4. Inicia o Loop de Shrink
IF @InitialSizeMB > @TargetSizeMB
BEGIN
    SET @TotalSteps = CEILING(CAST(@InitialSizeMB - @TargetSizeMB AS FLOAT) / @ChunkMB);
    
    WHILE @CurrentSizeMB > @TargetSizeMB
    BEGIN
        SET @CurrentSizeMB = @CurrentSizeMB - @ChunkMB;
        
        IF @CurrentSizeMB < @TargetSizeMB
            SET @CurrentSizeMB = @TargetSizeMB;

        SET @Message = FORMATMESSAGE('Shrink %d/%d - Reduzindo lote... Meta deste lote: %d MB', @CurrentStep, @TotalSteps, @CurrentSizeMB);
        RAISERROR(@Message, 10, 1) WITH NOWAIT;
        
        -- Executa o shrink
        DBCC SHRINKFILE (@FileName, @CurrentSizeMB);

        -- Verifica o tamanho real
        SELECT @CurrentSizeMB = size * 8 / 1024 
        FROM sys.database_files 
        WHERE name = @FileName;

        SET @CurrentStep = @CurrentStep + 1;
        WAITFOR DELAY '00:00:05'; -- Pausa para aliviar I/O
    END

    RAISERROR('Shrink finalizado com sucesso!', 10, 1) WITH NOWAIT;
END
ELSE
BEGIN
    RAISERROR('O arquivo já está no tamanho alvo ou não tem mais espaço em branco (livre) para encolher.', 10, 1) WITH NOWAIT;
END
GO

📊 Script 2: Acompanhando o Progresso em Tempo Real

Como o processo de shrink fragmentado pode levar algum tempo, é crucial saber o que está acontecendo nos bastidores. Abra uma nova aba (sessão) no seu SQL Server Management Studio e rode a consulta abaixo.

Ela traduzirá o processamento interno em métricas fáceis de ler, mostrando a porcentagem de conclusão e os minutos restantes para o lote atual finalizar:

SQL

-- Script para acompanhar o andamento de cada shrink
SELECT 
    session_id,
    command,
    status,
    percent_complete AS [% Concluída do Lote Atual],
    estimated_completion_time / 1000 / 60 AS [Minutos Restantes (Lote Atual)],
    total_elapsed_time / 1000 / 60 AS [Minutos Decorridos]
FROM sys.dm_exec_requests
WHERE command IN ('DbccSpaceReclaim', 'DbccFilesCompact')
   OR command LIKE 'DBCC%';

 
 
 

Posts recentes

Ver tudo

Comentários


Logo_quadrada.png

CLOUD DB LTDA - 28.961.479/0001-41

© 2020 Direitos Reservados CloudDB ®  O plágio é considerado crime e sua principal referência é a lei 9.610 - ♥ SEO WIX Partner - Phoenix

bottom of page