Skip to content

Instantly share code, notes, and snippets.

@haf
Created May 14, 2014 19:58
Show Gist options
  • Save haf/f3a6eac58c630fa0f843 to your computer and use it in GitHub Desktop.
Save haf/f3a6eac58c630fa0f843 to your computer and use it in GitHub Desktop.

Alternatives for shrinking

Pieces:

  • Simple Recovery Model
  • Bulk of < 4k items
  • Rebuild index at end
  • Ensure no user is working in app when you do it

Something like:

-- First do the backup, incrementally or otherwise
USE master;
GO

-- Ensure no users in DB, creating things you're going to destroy the TX log for
ALTER DATABASE DB_0000
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO

-- Use the large DB so you target it
USE DB_0000
GO

-- Ensure you have a clean tx log by backing it up
BACKUP DATABASE DB_0000
TO DISK = 'C:\MSSQL\BACKUP\DB_0000.Bak'
   WITH FORMAT,
   NAME = 'Full Backup of CV Hoarder'
GO

-- Now, don't log so much to disk!
ALTER DATABASE DB_0000 SET RECOVERY SIMPLE;
GO

-- Go through all items in the table and older than Date X and delete them in bulk,
-- but not everything at once or you'll run out of disk and crash like you did today.
-- Stop if there's not enough disk space. You may have to syntax check this code:
WHILE EXISTS (
  SELECT 1 AS MatchCVs, CVId
  FROM dbo.CVs
  WHERE CVs.InsertDate < '2010-01-01 00:00:00'
  INNER JOIN (
    SELECT
      CASE
        size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableMiB
        WHEN AvailableMiB > 10240
          1
        WHEN AvailableMiB <= 10240
          0
      END AS MatchMiB
    FROM sys.database_files
  ) AS FreeSpace
  ON FreeSpace.MatchMiB = MatchCVs)
BEGIN
  -- delete old CVs, everything a tx, be explicit!
  BEGIN TRANSACTION
    DELETE TOP(4900) FROM dbo.CVs WHERE CVs.InsertDate < '2010-01-01 00:00:00';
  COMMIT TRANSACTION
END
GO

BEGIN TRANSACTION
  -- You need to check if it stopped from over-usage of log file, or from
  -- it being done:
  SELECT 
    size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableMiB
  FROM sys.database_files
END TRANSACTION
GO

-- If needed, see above!
DBCC SHRINKFILE (DB_0000_DataFile, 10240) TRUNCATEONLY;
GO

BEGIN TRANSACTION
  -- rebuild the index because it's fragmented now
  ALTER INDEX ALL ON dbo.CVs REBUILD;

  -- rebuild query execution plans
  UPDATE STATISTICS dbo.CVs WITH SAMPLE 10 PERCENT;

  -- some stats from the delete
  SELECT  database_transaction_log_bytes_used
  FROM    sys.dm_tran_database_transactions
  WHERE   database_id = db_id('DB_0000');
END TRANSACTION
GO

-- Change back to full recovery mode
ALTER DATABASE DB_0000 SET RECOVERY FULL;
GO

-- Ensure no users in DB
ALTER DATABASE DB_0000
SET MULTI_USER
WITH ROLLBACK  IMMEDIATE;
GO

References:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment