Introduction
What is Shrink Database? In reality to increase SQL Server disk space, shrink database task is used. This article will demonstrate the procedure to shrink the database transaction log.
Background
Occasionally, you might need to conduct database maintenance whether you have the pre-packaged MSDE or the full version of SQL Server. This maintenance should be conducted after you have deleted large amounts of data from the database (Example.mdf and Example_log.ldf). Usually this occurs if you delete a large number of events from the event log. Even after data is removed, the .mdf and .ldf files need to be compacted (similar to an Outlook *.pst file after deleting emails) in order to recover disk space and increase efficiency, and also to reduce seek time.
More details will be available from this link.
Using the Code
Before we start using this code / how the code works as well, I would like to share some basic information regarding the database shrink process.
The process has several control parameters, most of the time you only need to worry about the first four as these are the big controls whereas the fifth is simply a fine tuning control which rarely needs to come into play.
Parameter Description at a Glance
SET @LogicalFileName =’Logical file name’;
SET @MaxMinutes = 5;
SET @NewSize =100;
SET @Factor = 1.0;
DBCC SHRINKDATABASE
Shrinks the size of the data and log files in the specified database.
More details will be available from this link.
Using this code is very simple. Just follow the given procedure:
- Set the name of your database.
Example: This is the name of the database for which the log will be shrunk.
USE [databasename] put the logical name of the database to replace the database name.
- Set the logical file name.
Example: Use sp_helpfile
to identify the logical file name that you want to shrink.
SET @LogicalFileName = 'database_Log';
*Do the same here replace the database_log
for the database log name.
*Run the script, if it doesn't run then it's down to the logical name of the database that isn't right.
Note: This has been tested successfully on SQL 2000, 7 and 2005 databases. 40 GB went down to under 1 GB, 176GB went down to 105MB.
The code example is given below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spShrinSQLServerTransactionLog]
@DB_NAME VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON
DECLARE @LogicalFileName SYSNAME
,@MaxMinutes INT
,@NewSize INT
,@Factor FLOAT
SET @LogicalFileName = @DB_NAME;
SET @MaxMinutes = 5;
SET @NewSize =100;
SET @Factor = 1.0;
DECLARE @OriginalSize INT,
@StringData VARCHAR(500)
SELECT @OriginalSize = size
FROM sysfiles
WHERE name = @LogicalFileName;
SELECT @StringData = 'Original Size of ' + db_name() + ' LOG is ' +
CONVERT(VARCHAR,@OriginalSize) + ' 8K pages or ' +
CONVERT(VARCHAR,(@OriginalSize*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName;
PRINT @StringData;
PRINT ''
IF ( OBJECT_ID('[dbo].[DummyTransaction]') IS NOT NULL )
DROP TABLE [DummyTransaction]
CREATE TABLE [DummyTransaction]( [DummyColumn] CHAR(8000) NOT NULL );
DECLARE @Counter INT,
@MaxCount INT,
@StartTime DATETIME,
@TruncLog VARCHAR(500)
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
SET @TruncLog = 'BACKUP LOG [' + db_name() + '] WITH TRUNCATE_ONLY';
EXEC (@TruncLog)
IF @OriginalSize / @Factor > 50000
SET @MaxCount = 50000
ELSE
SET @MaxCount = @OriginalSize * @Factor
PRINT 'Minimum Quantity : '+ CAST( @MaxCount AS VARCHAR(10) )
PRINT 'Maximum Time : '+ CAST( @MaxMinutes AS VARCHAR(10) )+' _
minutes ('+CAST( @MaxMinutes*60 AS VARCHAR(10) )+' seconds)'
PRINT ''
SET @Counter = 0;
SET @StartTime = GETDATE();
WHILE (
(@MaxMinutes*60 > DATEDIFF(ss, @StartTime, GETDATE())) AND
(@OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)) AND
((@OriginalSize * 8 / 1024) > @NewSize)
)
BEGIN
WHILE (
(@Counter < @MaxCount) AND
(@MaxMinutes*60 > DATEDIFF(ss, @StartTime, GETDATE())) AND
(@OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)) AND
((@OriginalSize * 8 / 1024) > @NewSize)
)
BEGIN
INSERT INTO [DummyTransaction] VALUES ('Fill Log')
DELETE FROM [DummyTransaction]
SELECT @Counter = @Counter + 1
IF ROUND( @Counter , -3 ) = @Counter
BEGIN
PRINT 'Padded '+LTRIM( CAST( @Counter*8 AS VARCHAR(10) ) )+_
'K @ '+LTRIM( CAST( DATEDIFF( ss, @StartTime, GETDATE() ) _
AS VARCHAR(10) ) )+' seconds';
END
END
EXEC( @TruncLog )
END
PRINT ''
SELECT @StringData = 'Final Size of ' + db_name() + ' LOG is ' +
CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName;
PRINT @StringData
PRINT ''
DROP TABLE [DummyTransaction];
PRINT '*** Perform a full database backup ***'
SET NOCOUNT OFF
END
GO
Conclusion
I hope that this article might be helpful to you. Enjoy!
History
- 25th July, 2009: Initial post