Goodbye, old friend
SQL Server 2000, I will miss you. Two months ago, my last customer running on SQL Server 2000 took the plunge, and upgraded to SQL Server 2005. Last night between 9pm and 1:30am this morning,… Goodbye, old friend
SQL Server 2000, I will miss you. Two months ago, my last customer running on SQL Server 2000 took the plunge, and upgraded to SQL Server 2005. Last night between 9pm and 1:30am this morning,… Goodbye, old friend
I was curious how SQL Server saves bit columns in a row. According to Microsoft Docs, it’s fairly straight-forward:
The SQL Server Database Engine optimizes storage of bit columns. If there are 8 or less bit columns in a table, the columns are stored as 1 byte. If there are from 9 up to 16 bit columns, the columns are stored as 2 bytes, and so on.
But how does the data actually look on the page? Let’s find out.
Here’s our test table:
USE [tempdb]
GO
CREATE TABLE [dbo].[TestBit] (
[TestID] [int] IDENTITY(1, 1) NOT NULL,
[BitField] [bit] NOT NULL DEFAULT(0),
CONSTRAINT [PK_TestBit] PRIMARY KEY CLUSTERED ([TestID] ASC)
)
GO
-- Insert four rows
INSERT INTO [dbo].[TestBit] DEFAULT VALUES
INSERT INTO [dbo].[TestBit] DEFAULT VALUES
INSERT INTO [dbo].[TestBit] DEFAULT VALUES
INSERT INTO [dbo].[TestBit] 1
GO
Now let’s have a look inside the row.
We can either use the classic DBCC IND
method:
DBCC IND('tempdb', '[dbo].[TestBit]', 1);
Or we can use sys.dm_db_database_page_allocations
on SQL Server 2012 (courtesy of Jason Strate):
SELECT allocated_page_file_id,
allocated_page_page_id
FROM sys.dm_db_database_page_allocations(DB_ID('tempdb'),
OBJECT_ID('[dbo].[TestBit]'), 1, NULL, 'DETAILED')
WHERE is_allocated = 1
AND page_type = 1;
GO
Notice how I asked for Page Type 1, which according to Paul Randal, is a data page.
My output to the modified Strate Script looks like this:
allocated_page_file_id | allocated_page_page_id |
3 | 30 |
Now we output to the console:
DBCC TRACEON (3604)
DBCC PAGE(tempdb, 3, 30, 3)
Here’s the first row, with the bit column set to 0 (I have edited the output to just display the row data, highlighting the column data):
00000000: 10000900 01000000
00
020000
Here’s the last row, with the bit column set to 1:
00000000: 10000900 04000000
01
020000
(Back to Paul Randal’s series on the Storage Engine, in Anatomy of a Record, we know that the 02
in the above row, after the byte that stores our bit column, is part of the NULL bitmap. Two bytes count the number of columns in the record, which in this case is 2.)
Now let’s mix things up and see how the row looks with eight columns that are bits.
DROP TABLE [dbo].[TestBit]
GO
CREATE TABLE [dbo].[TestBit] (
[TestID] [int] IDENTITY(1, 1) NOT NULL,
[BitField1] [bit] NOT NULL DEFAULT(1),
[BitField2] [bit] NOT NULL DEFAULT(0),
[BitField3] [bit] NOT NULL DEFAULT(1),
[BitField4] [bit] NOT NULL DEFAULT(0),
[BitField5] [bit] NOT NULL DEFAULT(1),
[BitField6] [bit] NOT NULL DEFAULT(0),
[BitField7] [bit] NOT NULL DEFAULT(1),
[BitField8] [bit] NOT NULL DEFAULT(0),
CONSTRAINT [PK_TestBit] PRIMARY KEY CLUSTERED ([TestID] ASC)
)
GO
In our first example with the larger table, I’ll set the bits alternating on and off to see how it looks.
INSERT INTO [dbo].[TestBit] DEFAULT VALUES
GO
The DBCC PAGE
output (edited again) shows us the following:
00000000: 10000900 01000000
55
090000 00
(Notice the NULL bitmap now reflects that we have 9 columns.)
How about all of the bit columns set to 0, except the first one?
00000000: 10000900 01000000
01
090000 00
All of them set to 1 except the first one?
00000000: 10000900 01000000
fe
090000 00
All of them set to 0 except the last one?
00000000: 10000900 01000000
80
090000 00
And finally, all of them set to 1 except the last one:
00000000: 10000900 01000000
7f
090000 00
Books Online also says that if you have more than 8 bits in a row, additional bytes are assigned to accommodate each set of eight. Here’s what we get when we add just one more column to our table:
00000000: 10000a00 01000000
7f21
0a00 0000
(Our NULL bitmap shows 0a
for 10 columns.)
I’ve now completely satisfied my curiosity about how bit columns are stored in SQL Server.
And don’t forget:
DBCC TRACEOFF (3604)
GO
DROP TABLE [dbo].[TestBit]
GO
Thank you for reading.
Photo by Vlad Tchompalov on Unsplash.
The SQL Server 2000 Duplicate Index Finder has been updated. I presented the newest version tonight at the SQLskills.com immersion event open night. Grab the scripts here. Changes include a workaround for appending RID and… Duplicate Index Finder updated
A customer is running in a SQL Server 2000 environment, 32-bit AWE mode, on 64-bit Windows 2003 R2. The server has 16GB of RAM and 8 logical CPU cores. It’s running under VMWare. Storage is… The curious case of RESOURCE_SEMAPHORE
On SuperUser.com, a question came up about how to do a proper Linux backup, including the applications installed, and associated configurations. In light of a previous post I wrote about backups and run books, I… Where Do I Start With A Run Book?
I’ve been vocal for some years about the importance of backups, and I have zero sympathy for anyone who does not have good backups*. This comes with (very) painful experience: a few years ago, during… On the importance of good backups
The latest version of sp_WhoIsActive (and apparently last for SQL Server 2005/2008, according to Adam Machanic), was released a week ago. Yesterday, out of curiosity piqued by my recent three-week SQLskills training, I decided to… Adventures in @BlobEater, sp_WhoIsActive and DBCC CHECKDB
With permission from Kimberly Tripp, the creator of the fantastic duplicate index finder for SQL Server 2005 and 2008, I have ported this duplicate index finder to SQL Server 2000. I am fortunate in many… Remove duplicate indexes in SQL Server 2000
Kimberly Tripp has a very neat series of stored procedures on her blog which are rewrites of sp_helpindex. Unfortunately for those of us with customers still using SQL Server 2000, these scripts are useless, because… My brain hurts
Via Tim Radney, here’s a quick and easy way to increase the number of error logs from the default of six. The blog post also has a walkthrough in SQL Server Management Studio if you… Increasing the number of SQL Server Error Logs
Today at the clinic, we did the second of three phases of network reorganisation. In the first phase, which we completed a week ago, our new server was set up with the EMR software, all… What I did today
For those of you battling with a 64-bit SQL 2005 Server linking to 32-bit SQL 2000 Servers, here’s a handy solution. This problem has been plaguing us for a while now, and today I made… Link 64-bit SQL Server 2005 to 32-bit SQL Server 2000