Identical tables, identical columns, identical records, but why different record sizes?
USE [test]
GO
CREATE TABLE [dbo].[mybit](
[col1] [bit] NOT NULL,
[col2] [bit] NOT NULL,
[col3] [bit] NOT NULL,
[col4] [bit] NOT NULL,
[col5] [bit] NOT NULL,
[col6] [bit] NOT NULL,
[col7] [bit] NOT NULL,
[col8] [bit] NOT NULL,
[col9] [bit] NULL
)
GO
INSERT INTO [dbo].[mybit]
VALUES (1,1,1,1,1,1,1,1,NULL)
GO 2
DBCC IND(test, mybit, -1);
GO
DBCC TRACEON(3604);
DBCC PAGE(test, 1, '#pagenumber', 1);
Both records are 10 bytes in size.
CREATE TABLE [dbo].[mybit2](
[col1] [bit] NOT NULL,
[col2] [bit] NOT NULL,
[col3] [bit] NOT NULL,
[col4] [bit] NOT NULL,
[col5] [bit] NOT NULL,
[col6] [bit] NOT NULL,
[col7] [bit] NOT NULL,
[col8] [bit] NOT NULL,
)
GO
INSERT INTO [dbo].[mybit2]
VALUES (1,1,1,1,1,1,1,1)
GO
ALTER TABLE [dbo].[mybit2] ADD [col9] [bit] NULL
GO
INSERT INTO [dbo].[mybit2]
VALUES (1,1,1,1,1,1,1,1, NULL)
GO
DBCC IND(test, mybit2, -1);
GO
DBCC TRACEON(3604);
DBCC PAGE(test, 1, '#pagenumber', 1);
One record is 9 bytes in size and another is 10.
Best Answer
Thomas Cleberg is correct.
The first row you insert into
bit2
shows up in DBCC page asThis breaks down as follows
(If you wonder why there is a "spare" byte. This is explained here. It is to allow the row to be replaced by a forwarding pointer should the need arise. The value of it is arbitrary. For me it was
0x63
. For you it looks like it was0x00
)After you alter the table and add a new column with a
NULL
value (or a runtime constant default value in SQL Server 2012+ enterprise edition) then this is a metadata only change. SQL Server doesn't update existing rows. It can deduce from the column count stored in the row that the value forcol9
should beNULL
for that row. The change will be written out next time the row is updated.Newly inserted rows will get written out in full though. Two extra bytes are needed because the single byte in the fixed data section is full up with values for bit columns 1-8 so an additional byte is needed for bit columns 9 to 16. Additionally the Null bitmap grows by a byte too. However there is no need to retain that "spare" byte to keep the rowsize at a minimum level so the net effect is an increase in one byte.