How do I shrink all files quickly for all databases?

When you do "Tasks -> Shrink" from the GUI it actually issues a DBCC SHRINKDATABASE command behind the scenes. Try it. When the dialog box comes up, don't click the "OK" button. Instead, click the "Script" button. You'll see the command in a query window. Combine that with a query on sys.databases (leave out master and msdb), and you can make a script to shrink all of the databases.

For example (taken from jcolebrand's comment):

SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4;

Copy the output of that query and run it to shrink all your files.


How about one single line of sql statement?

Please read this very interesting blog post before executing the following sql statement.

EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'

DBCC SHRINKDB (and its cousin SHRINKFILE) are extremely slow, because there is a lot of single threaded execution going on in that code.

A much faster way to shrink a database file is this:

  • Allocate a new filegroup to database
  • Make this filegroup as large as it has to be (use sp_spaceused to determine just how large)
  • Rebuild all indexes to this new filegroup
  • Drop the old filegroup

Because index rebuilds are massively parallel, this technique often results in a much faster shrinking of the database. Of course, it does require you to have a bit of extra space for the new filegroup while the process is going on. However, you only need enough space in the new filegroup to hold the largest filegroup in the instance (as you will be reclaiming space as you go along).

This technique also has the added benefit of defragmenting your indexes in the process.