I think we can all agree that Data Compression is a great new functionality in SQL Server 2008. I know many of you have been experimenting with it but there was one little catch I wanted you to be aware of.When you apply page compression to a table the pages get compressed when they are full but there is an exception as you would have expected. When you have a heap the newly allocated pages are NOT compressed until you rebuild the table (or remove and reapply compression or add and remove a clustered index) unless you are using BULK INSERT.
I have added a test script so you can see it with your own eyes.
First the clustered table:
SET NOCOUNT ONGO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[myClusteredTable]') AND type in (N'U'))DROP TABLE [dbo].[myClusteredTable]GO
SET ANSI_NULLS ONGO
SET QUOTED_IDENTIFIER ONGO
SET ANSI_PADDING ONGO
CREATE TABLE [dbo].[myClusteredTable]( [ID] [int] IDENTITY(1,1) NOT NULL, [TheDate] [date] NOT NULL, [TheTime] [time](7) NOT NULL, [SomeFiller] [varchar](256) NOT NULL, CONSTRAINT [PK_myClusteredTable] PRIMARY KEY CLUSTERED ( [ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
GO
SET ANSI_PADDING OFFGO
--Add some records to the table with varying lengthINSERT INTO dbo.myClusteredTable VALUES (SYSDATETIME(), SYSDATETIME(), REPLICATE('W', CEILING(RAND() * 100) + 1)) GO 15000
--Check the space usedsp_spaceused myClusteredTable
--Now apply compressionALTER TABLE [dbo].[myClusteredTable] REBUILD PARTITION = ALLWITH (DATA_COMPRESSION = PAGE)GO
--Check the space usedsp_spaceused myClusteredTableGO
--Add some more records to the tableINSERT INTO dbo.myClusteredTable (TheDate, TheTime, SomeFiller) SELECT TheDate, TheTime, SomeFiller FROM myClusteredTableGO
--Check the space used againsp_spaceused myClusteredTableGO
DROP TABLE myClusteredTable
As you can see the compression keeps going even when you insert new rows.But what about the heap?
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[myHeap]') AND type in (N'U'))DROP TABLE [dbo].[myHeap]GO
CREATE TABLE [dbo].[myHeap]( [ID] [int] IDENTITY(1,1) NOT NULL, [TheDate] [date] NOT NULL, [TheTime] [time](7) NOT NULL, [SomeFiller] [varchar](256) NOT NULL, CONSTRAINT [PK_myHeap] PRIMARY KEY NONCLUSTERED ( [ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
--Add some records to the table with varying lengthINSERT INTO dbo.myHeap VALUES (SYSDATETIME(), SYSDATETIME(), REPLICATE('W', CEILING(RAND() * 100) + 1)) GO 15000
--Check the space usedsp_spaceused myHeap
--Now apply compressionALTER TABLE [dbo].[myHeap] REBUILD PARTITION = ALLWITH (DATA_COMPRESSION = PAGE)GO
--Check the space usedsp_spaceused myHeapGO
--Add some more records to the tableINSERT INTO dbo.myHeap (TheDate, TheTime, SomeFiller) SELECT TheDate, TheTime, SomeFiller FROM myHeapGO
--Check the space used againsp_spaceused myHeapGO
--Rebuild the heap?ALTER TABLE myHeap REBUILDGO
--What about a bulk insert?BULK INSERT TestDB.dbo.MyHeap FROM 'c:\temp\test.txt' WITH ( FORMATFILE='c:\temp\myHeap.xml', KEEPIDENTITY, TABLOCK )GO
--Seems compression was indeed applied with BULK INSERT, go ahead and drop the test tableDROP TABLE myHeap
This was tested on SQL Server 2008 SP1 + CU2 (build 10.0.2714).