Originally published on DMMaxwell.WordPress.com.
SQL Server Performance Tuning – Shrink Is A Four Letter Word
Recently, I’ve been noticing some large-scale log growth on some of my developer SQL servers, which has been causing them to run out of disk space. Though shrinking files is almost universally a bad idea, there is a time and a place for doing so provided the ramifications of shrinking are understood. Needing to shrink a log file indicates that either we’re operating on more data than we expected, or operating inefficiently. Either way, it’s almost always the result of unplanned circumstances. Under such circumstances, you can’t always use the option you want to. Sometimes you have to do something regrettable.
When *NOT* to shrink:
- When the growth happens in a Data file. Shrinking is going to rob you of free space required for index maintenance, not to mention fragmenting the hell out of your existing indexes, making them near useless.
- When the growth is in TempDB. It can cause corruption. Either add TempDB files, or kill the transaction and recreate tempdb. You’ll need to restart SQL Server for that, and killing said transaction that big may cause a very long rollback. You’ve been warned.
- As part of regular maintenance. If your log files are growing repeatedly, then they’re trying to get to the size they need to be in order to handle your workload. Why are you shrinking them? What do you have against them? They have dreams, too Fix the workload, not the log files.
Alternatives to shrinking:
When to shrink. I can only think of two situations off the top of my head
- Under an emergency where other workloads on the same disk are affected and there’s no additional disk elsewhere for another log file.
- When a database is being archived / retired, and will be set to read-only. Even in that case, you wouldn’t just shrink the DB. See Retiring a Database.
Benefits to shrinking:
- Free disk space.
- That’s about it.
Caveats to shrinking:
- Massive performance hit during re-growth, as all transactions must be suspended.
- Massive performance hit due to file fragmentation on re-growth.
- Massive performance hit due to internal fragmentation on shrink.
- Massive perfor . You get the idea.
So really, we want to avoid shrinking log files wherever possible. The best way to avoid shrinking is to properly size files to begin with. Make sure you have enough room for your transactions to run. If you have large transactions or volumes of data to work with, one good way to avoid file growth is to batch large transactions into smaller groups. i.e. Instead of inserting 5M rows, insert 100k rows at a time, 50 times. This can actually be faster than a single large insert, as you’re not stuck waiting for the log file to grow to accommodate 5M records.
Some growth may still occur since, let’s face it, we have a lot of data to work with. What we want to avoid is large, recurring growth. Remember that when the log file must grow, all transactions are suspended. If you are only growing slightly, that may not be a problem, but when you have 100GB of growth, that’s going to stop you in your tracks for the duration of the growth.
If you must shrink a log file due to uncontrolled or unexpected growth, you can use the SHRINKFILE command, but with one caveat – I would recommend shrinking the file by half instead of to its smallest size. This way, future growth may be avoided while queries are tuned to use less log space. For example, if a log were to grow to 40GB, after averaging a size of 2GB, I would shrink the log to 20GB, like this:
USE <DatabaseName>; DBCC SHRINKFILE(<file ID>,<target size>);
USE BigLogDB; DBCC SHRINKFILE(2,20000);
2 is the ID of the log file for most databases. You can use sp_helpfile on a database to check that. 20000 is the target size, which is always in MB. Shrinking requires sysadmin or diskadmin permissions, which some developers do have. I can also assist you with these tasks as needed. Another advantage to this is that it gives us an idea of how large the production log files will need to be to accommodate new SQL code.
Also, I would like to stress that shrinking is used as a temporary fix, not as a workaround, and *never* as part of regular maintenance. If you have a job on a server that is regularly shrinking log files, then you either need more disk space or smaller transactions. Regular shrinking is a sign that something bad is going on. Also, while shrinking can be considered on log files, it is almost never a good idea to shrink a data file. Avoid using SHRINKDATABASE.
Thanks for reading.