I’m speaking tomorrow
The local SQL PASS chapter in Calgary is hosting yours truly as the speaker for this month. I only have an hour, which I will easily go over, to talk about how I make SQL… I’m speaking tomorrow
The local SQL PASS chapter in Calgary is hosting yours truly as the speaker for this month. I only have an hour, which I will easily go over, to talk about how I make SQL… I’m speaking tomorrow
As the title says, I’ll be speaking at the Calgary SQL PASS User Group on 19 August 2015. My topic is SQL Server Performance Tuning Starter Kit, where I will tell you as much as… Speaking at Calgary SQL PASS User Group on 19 August 2015
I presented for fifty minutes on 27 June 2015, for my first ever SQLSaturday talk. The amount of time I put into that presentation is easily 200 hours, not counting my experience as a college… How I prepared for my first ever SQLSaturday session
Yesterday at SQLSaturday #407 in Vancouver, I announced availability of a free tool to synchronise and restore your SQL Server backups using Azure Blob Storage. It can work alongside your existing backup process, and leverages… Announcing Azure Blob Storage Sync and Restore
Steve Stedman has been running a contest over on his site, the Database Corruption Challenge, which I discovered last week quite by chance through Twitter. Not to brag, but I’ve been the fastest to solve… Database Corruption Challenge
This is the final entry in my #SQLNewBlogger challenge. You can read the previous entries here: Part 1: The Intersection of Art and Science Part 2: The Art of Improvisation Part 3: What Motivates You?… Total Recall
This is the second post in my four part series for the #SQLNewBlogger Challenge. You can read the first part here. On Saturday, 28 March 2015, I moved three servers and various networking equipment from… The Art of Improvisation
This is the first post in a series of four, where Ed Leighton-Dick, via Brent Ozar, is proposing that we SQL Server folks participate in the #SQLNewBlogger Challenge. I write a fair number of words… The Intersection of Art and Science
Your production environment needs Date and Number tables, to help you Get Stuff Done in sets instead of RBAR*. Doug Lane has a video on Why You Simply Must Have a Date Table. I really… Do it now: Date and Number tables
Today we went live with a product we’ve been working on for A Long Time, in which a team of five has put in A Lot Of Work. During the walk-through with the customer, loading… Assumption Sandwich
I’ve been privileged to attend the 2014 Summit in Seattle this year, which has been a great experience thus far. More importantly, I’ve been speaking to the members of the SQL Server family, getting to… SQL PASS Summit 2014
Five months from now, Microsoft will stop supporting Windows XP. As Tim Rains points out, running Windows XP after this date will effectively be an open invitation for attack. XP will, in his words, be… End of Life for Microsoft Windows XP and Server 2003: Six-One or Up
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.
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?