When using the DBCC SHRINKDATABASE statement, you cannot shrink a whole database to be smaller than its original size. Therefore, if a database was created with a size of 10 MB and grew to 100 MB, the smallest the database could be reduced to is 10 MB, even if all the data in the database has been deleted.
However, you can shrink the individual database files to a smaller size than their initial size by using the DBCC SHRINKFILE statement. You must shrink each file individually, instead of trying to shrink the whole database.
Initial size is not just 3MB, it is taken from the model database (if not specified during the creation of your user database.) So assuming you haven't specified a initial size during the creation of your user db and you haven't altered the model database file sizes after you have created your userdb you can do the following:
--Create testDB
CREATE DATABASE [TEST_100]
GO
--grow your database file size
ALTER DATABASE [Test] MODIFY FILE ( NAME = N'Test', SIZE = 100MB )
GO
--switch context
USE [TEST_100]
GO
--Find size of modelDB mdf file, this is your initial file size used for the userdb
DECLARE @TargetFileSize int
SELECT @TargetFileSize = (size * 8 / 1024)
FROM sys.master_files
WHERE database_id = 3 --model database
AND file_id= 1 --first file is mdf, assuming you have a model with just one mdf. If you have multiple files, change for the one you need to find.
--shrink the the first file of your current database to the target size that you just found.
DBCC SHRINKFILE (1,@TargetFileSize)
EDIT
Okay, some extra info is needed after your edits and comments.
First of all. I feel that the "Initial size" label that you see when you look at the file properties in SSMS is a misnomer. Basically, your intial size is just a concept. It's the first size that is used during creation of the database. You can either explicitly specify this in the CREATE DATABASE
statement, or you can have SQL Server implicitly copy it from the model database by ommiting that information during creation.
However, once the database is created, from a DBA perpective there is no such thing as a "initial size" there is only one property visible for a DBA and that is: the actual size. Even the "Initial size" property in SSMS just shows actual size, not the initial size.
Well how come that DBCC SHRINKFILE
or DBCC SHRINKDATABASE
"know" the initial size then? Even after you have changed the size. Interesting question.
The first page of a dattabase file is the file header page. In there you have, amongst others, 2 properties: size and minsize.
At creation of the file, both file header properties get filled with the inital value:
DBCC TRACEON(3604)
--parameters for DBCC PAGE: (Dbname, fileID, pageID, outputTypeID)
DBCC PAGE('Test_100',1,0,3)with tableresults
Both sizes are in the amount of data pages. In this case. 288 data pages.
Now if I alter the file size:
ALTER DATABASE [test_100] MODIFY FILE ( NAME = N'test', SIZE = 50MB )
You can see that the "size" property is changed to reflect the new size. However, the "MinSize" property still contains the "Initial" size. It's the minimal size to which the shrink command will go.
However, having said all this. I still don't understand why you want to complicate things by first altering the initial size and then shrink to that initial size. Instead of just shrinking directly to a targetsize.
Anyway, to answer your question. The "initial" size is not exposed as a property to the user/dba.
Best Answer
Exactly how did you run the
SHRINK
commands? My understanding is that by default it just releases unused space at the end of the file, but you can also have the database compact itself first to make more space available. This is a slow and expensive operation, though; around an hour per 10 GB in my recent experience.That said, I suspect your database is using more space than it ought to due to fragmentation. If you run a query like this:
...you'll see the tables and indices which are both large and badly fragmented. Running
ALTER INDEX MyIndx ON MyTBl REBUILD
on a few of those should recover some space. As Aaron Bertrand said, you probably don't want to actually free this space withSHRINK
; your database will need it sooner or later.Heap tables are prone to wasted space; using
ALTER TABLE MyTbl REBUILD
on your bigger tables may help too.