Blog

We need your help.

SQL Server
2 Comments

Doctors Without Borders is a truly awesome charity. Medical professionals volunteer their own personal time to go to war-torn countries and solve issues of world health.

SQL Server community member, MCM, and all-around-good-guy Argenis Fernandez organizes Argenis Without Borders, a giving event to help. Last year, the SQL Server community helped raise $13,000 for this well-deserving charity.

doctors-without-bordersNow it’s your turn. Please donate $25 if you can. It would mean a lot to me, and I know it’d mean a lot to people all over the world who urgently need medical help. You’ve got a great job – it’s your turn to give back.

Donate now. Seriously, right now.


AlwaysOn AG Databases Need Bigger Log Files

Doug demonstrates what he's going to do to the failed replica.
Doug demonstrates what he’s going to do to the failed replica.

One of your SQL Servers is going to fail.

When one of your AG members goes down, what happens next is just like opening a new SSMS window and typing BEGIN TRAN. From this moment forwards, the transaction log starts growing.

And growing. And growing.

SQL Server is waiting for that failed replica to come back online and start synchronizing again. The transaction log has to contain all of the data necessary to bring that once-failed replica back up to speed, to the current point in time. It doesn’t matter whether this replica is sync or async, important failover partner or an unimportant reporting server.

After every 4 hours of outage troubleshooting (at 4 hours in, 8 hours, 12 hours), I look at the facts:

  • How much free space do I have left on the log file drive?
  • How long will it take to reseed the failed replica by using a full backup?
  • Based on these, should I remove the failed replica from the Availability Group?

This means at minimum, my AG replicas all need enough space to have 4 hours of transaction log activity. I can buy myself more time by disabling index defrag/rebuild jobs as soon as a replica fails, too. (In a perfect world, I’d code that into my index rebuild jobs, but that’s left as an exercise for the reader.)

After the emergency finishes, I don’t bother shrinking the log files back down – because after all, another replica is going to fail. It’s not a matter of if – it’s just a matter of when.

Knowing that all this is going to happen, it makes sense to pre-grow/size your transaction log files large enough to handle at least 4 hours of activity without a log backup. After all, when I’m troubleshooting an availability emergency, I don’t want to waste time troubleshooting a performance emergency. If my AG databases are constantly freezing up while they grow the log files, it’s going to be a bad distraction from the problem I really need to focus on.


Make Technical Decisions Easily With This One Trick

SQL Server
12 Comments

Decisions are emotional, right? Brent loves Sanka and I love Postum. We fight about it all the time. But when we wanted to settle the debate once and for all, we engineered a test to figure out who was right. You can do the same thing to take the personal investment out of technical decisions at work.

Check Yourself at the Door

The first thing you need to remember is that your opinions are just as valid everyone else involved. You need to move those aside and be ready to be wrong.

If the other people involved don’t want to play along, just tell them “Heck, I’d be happy to be wrong because I’ll learn something.” It’s not a bet or a contest, you’re just offering up your willingness to be wrong. Being wrong is great, especially when it’s your turn to be right later on.

Test, Test, Test

This dog knows more science than I do
This dog knows more science than I do

The next step to making that decision is to figure out a test. This test has to depend on your different opinions. The purpose of this test is to get your opinions out of the conversation.

Doing this correctly is really hard. You need to figure out:

  • What are both sides saying?
  • Which metrics will prove both points?
  • What won’t prove anyone’s points?
  • What’s the fastest way to test both options?
  • What’s a realistic scale to for testing?
  • What’s the worst that could happen if either side is right?
  • What’s the worst that could happen if either side is wrong?
  • If you can only run one test, which test should you run?

Hey, You Said This Was Easy!

All of this sounds like a lot of work. It turns out being factually right is just as much work as being factually wrong. If you really want to make sure that you’re choosing the right solution to a problem you need to figure out which option is the most right way to solve the problem – both solutions could be good, but one just might be better. The only way to get to proof is to test everything.

The next time there’s an argument on your team, or between two teams, figure out the best way to test each side’s ideas instead of spending your time arguing about which solution is the best.

Of course, you could always just fight in the parking lot like school kids. I hear that works well, too.


Amazon EC2 Dedicated Hosts: Much Cheaper SQL Server Licensing

When you build SQL Servers in your data center, and you license the host with Enterprise Edition, you get the ability to run as many virtual SQL Servers as you want on that hardware.

In the cloud, though, you haven’t had that luxury. In the past, with Azure VMs and Amazon Web Services’ EC2 VMs, you’ve had to license each individual VM. You weren’t able to guarantee that your VMs all lived on the same host, so you had to pay through the nose.

aws_logoSoon, Amazon is fixing that with the ability to get your own EC2 Dedicated Hosts.

This is gonna be huge. You can license one AWS host, and then run as many SQL Server VMs on there as you want. Use the same cool AWS management tools, and dramatically cut your costs.

No word on release dates or pricing yet.


I’m on the Away From the Keyboard Podcast

Blogging, SQL Server
6 Comments
Away From the Keyboard Podcast
Away From the Keyboard Podcast

Cecil Phillip (@cecilphillip) and Richie Rump (@jorriss) interviewed me for their podcast, Away From the Keyboard.

In the half-hour discussion, we talked about:

  • Why I’m a huge believer in giving away stuff for free
  • How I got started with Topspeed Clarion, then moved to SQL Server
  • When I started blogging, and how that turned into a consulting company

Head on over to AFTK and listen, and stay tuned for part 2.


How to Download the Stack Overflow Database

Stack Overflow
207 Comments

I use a Microsoft SQL Server version of the public Stack Overflow data export for my blog posts and training classes because it’s way more interesting than a lot of sample data sets out there. It’s easy to learn, has just a few easy-to-understand tables, and has real-world data distributions for numbers, dates, and strings. Plus, it’s open source and no charge for you – just choose your size:

  • Tiny: 1.5GB database as of 2009: 1GB direct download from Github. Expands to a ~1.5GB database called StackOverflowMini with data from 2008-2009. Useful if you want to quickly deploy a Docker container with SQL Server on a Mac, but not very useful for query tuning demos because the data is so small.
  • Small: 10GB database as of 2010: 1GB direct download, or torrent or magnet. Expands to a ~10GB database called StackOverflow2010 with data from the years 2008 to 2010. If all you need is a quick, easy, friendly database for demos, and to follow along with code samples here on the blog, this is all you probably need.
  • Medium: 50GB database as of 2013: 10GB direct download, or torrent or magnet. Expands to a ~50GB database called StackOverflow2013 with data from 2008 to 2013 data. I use this in my Fundamentals classes because it’s big enough that slow queries will actually be kinda slow.
  • Large: 202GB database as of 2024-04: 31GB torrent (magnet.) Expands to a ~202GB SQL Server 2016 database. Because it’s so large, I only distribute it with BitTorrent, not direct download links.
  • For my Mastering training classes: specialized copy as of 2018/06: 47GB torrent (magnet.) Expands to a ~180GB SQL Server 2016 database with queries and indexes specific to my training classes. Because it’s so large, I only distribute it with BitTorrent, not direct download links.

After you download it, extract the .7Zip files with 7Zip. (I use that for max compression to keep the downloads a little smaller.) The extract will have the database MDF, NDFs (additional data files), LDF, and a Readme.txt file. Don’t extract the files directly into your SQL Server’s database directories – instead, extract them somewhere else first, and then move or copy them into the SQL Server’s database directories. You’re going to screw up the database over time, and you’re going to want to start again – keep the original copy so you don’t have to download it again.

Then, attach the database. It’s in Microsoft SQL Server 2016 format, so you can attach it to any 2016 or newer instance, be it Developer, Standard, or Enterprise Edition. If your SSMS crashes or throws permissions errors, you likely tried extracting the archive directly into the database directory, and you’ve got permissions problems on the data/log files.

As with the original data dump, this is provided under cc-by-sa 4.0 license. That means you are free to share this database and adapt it for any purpose, even commercially, but you must attribute it to the original authors (not me):

so-logo

What’s Inside the StackOverflow Database

I want you to get started quickly while still keeping the database size small, so:

  • All tables have a clustered index on Id, an identity field, with page compression turned on
  • No other indexes are included (nonclustered or full text)
  • The log file is small, and you should grow it out if you plan to build indexes or modify data
  • It only includes StackOverflow.com data, not data for other Stack sites

To get started, here’s a few helpful links:

Past Versions

I also keep past versions online too in case you need to see a specific version for a demo.

  • 2022-06 – 54GB torrent (magnet.) Expands to a ~430GB SQL Server 2016 database. This is the last export that includes the giant PostHistory table.
  • 2021-02 – 54GB torrent (magnet.) Expands to a ~401GB SQL Server 2016 database.
  • 2020-06 – 46GB torrent (magnet.) Expands to a ~381GB SQL Server 2008 database. This is the last export that can be used with SQL Server 2014 & prior.
  • 2019-12 – 52GB torrent (magnet.) Expands to a  ~361GB SQL Server 2008 database.
  • 2019-09 – 43GB torrent (magnet.) Expands to a  ~352GB SQL Server 2008 database. This is the last export licensed with the cc-by-sa 3.0 license.
  • 2019-06 – 40GB torrent (magnet.) Expands to a  ~350GB SQL Server 2008 database.
  • 2018-12 – 41GB torrent (magnet.) Expands to a ~323GB SQL Server 2008 database.
  • 2018-09 – 39GB torrent (magnet.) Expands to a ~312GB SQL Server 2008 database.
  • 2018-06 – 38GB torrent (magnet.) Expands to a ~304GB SQL Server 2008 database. Starting with this version & newer, the giant PostHistory table is included. As you can probably guess by the name, this would make for excellent partitioning and archival demos. As you might not guess, the NVARCHAR(MAX) datatypes of the Comment and Text fields make those demos rather…challenging.
  • 2017-12 – 19GB torrent (magnet.) Expands to a ~137GB SQL Server 2008 database.
  • 2017-08 – 16GB torrent (magnet), 122GB SQL Server 2008 database. Starting with this version & newer, each table’s Id fields are identity fields. This way we can run real-life-style insert workloads during my Mastering Query Tuning class. (Prior to this version, the Id fields were just INTs, so you needed to select the max value or some other trick to generate your own Ids.)
  • 2017-06 – 16GB torrent (magnet), 118GB SQL Server 2008 database. Starting with this torrent & newer, I broke this up into multiple SQL Server data files, each in their own 7z file, to make compression / decompression / distribution a little easier. You need all of those files to attach the database.
  • 2017-01 – 14GB torrent (magnet), 110GB SQL Server 2008 database
  • 2016-03 – 12GB torrent (magnet), 95GB SQL Server 2005 database
  • 2015-08 – 9GB torrent (magnet), 70GB SQL Server 2005 database

Why are Some Sizes/Versions Only On BitTorrent?

BitTorrent is a peer-to-peer file distribution system. When you download a torrent, you also become a host for that torrent, sharing your own bandwidth to help distribute the file. It’s a free way to get a big file shared amongst friends.

The download is relatively large, so it would be expensive for me to host on a server. For example, if I hosted it in Amazon S3, I’d have to pay around $5 USD every time somebody downloaded the file. I like you people, but not quite enough to go around handing you dollar bills. (As it is, I’m paying for multiple seedboxes to keep these available, heh.)

Some corporate firewalls understandably block BitTorrent because it can use a lot of bandwidth, and it can also be used to share pirated movies/music/software/whatever. If you have difficulty running BitTorrent from work, you’ll need to download it from home instead.


Does Creating an Indexed View Require Exclusive Locks on an Underlying Table?

An interesting question came up in our SQL Server Performance Tuning course in Chicago: when creating an indexed view, does it require an exclusive lock on the underlying table or tables?

Let’s test it out with a simple indexed view run against a non-production environment. (AKA, a VM on my laptop running SQL Server 2014.)

Tracing the Locks

To trace the locks, I just used one of the built-in XEvents templates tor tracing locks, added a filter so it only looked at locks from my current session (53), and set it to write to an event file. The query scripts out like this:

Creating the Indexed View

I test it out by creating and dropping the indexed view this way:

Now let’s analyze the locks!

I stop my trace and open up the event file. I click around in the magic XEvents toolbar and group by object_id and mode (that’s the lock mode). And here’s what I get:

Locks!
Locks!

The low object_ids are internal system tables. Object_id 526624919 =dbo.Posts. Object_id 843150049 = dbo.IndexMe.

Translating this out:

  • dbo.Posts required S and SCH_S locks
  • dbo.IndexMe required X, SCH_S, and SCH_M locks

We didn’t require exclusive locks on the underlying table. I did require shared locks, and creating this indexed view could require lots of IO or be part of a blocking chain with other transactions. But creating the indexed view only needed exclusive locks on the indexed view itself.


SQL Server 2016 CTP2.4: Maintenance Plan Changes

You can download the next preview of SQL Server 2016 today, and the announcement blog post touted a few improvements to maintenance plans. Oddly, the screenshots in the announcement were apparently done with Microsoft Paint, so I fired up a VM to see how things really look.

The DBCC CHECKDB step in the wizard now has checkboxes for physical only and tablock:

DBCC CHECKDB
DBCC CHECKDB

The index reorg task now lets you do LOB compaction, scan index stats, and then only optimize the index based on statistics:

Index Reorg
Index Reorg

The rebuild task has similar options in the GUI, plus options about keeping the index online:

Index Rebuilds
Index Rebuilds

Updating statistics – I honestly don’t remember what older versions looked like. (I don’t step through that wizard often.)

Updating Statistics
Updating Statistics

The options on the full backup task got some attention as well:

Full Backup Options
Full Backup Options

While improvements are usually a good thing, I gotta be honest: these screens are pretty haphazard. Stuff doesn’t line up, warnings don’t fit into boxes, and it feels terribly slapped together. It doesn’t give me a high level of confidence, certainly not enough to steer me away from Ola Hallengren’s much more powerful and flexible free scripts. I get it – not everybody wants to use add-on scripts – but I’m just not filled with confidence when I see these screens.

That could mean we’re still quite a ways away from a SQL Server 2016 release, which is good news and bad news.


Forgotten Maintenance – Cycling the SQL Server Error Log

SQL Server
54 Comments

Most of us get caught up in fragmentation, finding the slowest queries, and looking at new features. We forget the little things that make managing a SQL Server easier – like cylcing the SQL Server error logs.

What’s the Error Log?

The SQL Server error log is a file that is full of messages generated by SQL Server. By default this tells you when log backups occurred, other informational events, and even contains pieces and parts of stack dumps. In short, it’s a treasure trove of information. When SQL Server is in trouble, it’s nice to have this available as a source of information during troubleshooting.

Unfortunately, if the SQL Server error log gets huge, it can take a long time to read the error log – it’s just a file, after all, and the GUI has to read that file into memory.

Keep the SQL Server Error Log Under Control

It’s possible to cycle the SQL Server error log. Cycling the error log starts a new file, and there are only two times when this happens.

  1. When SQL Server is restarted.
  2. When you execute sp_cycle_errorlog
Change everything!
Change everything!

When SQL Server cycles the error log, the current log file is closed and a new one is opened. By default, these files are in your SQL Server executables directory in the MSSQL\LOG folder. Admittedly, you don’t really need to know where these are unless you want to see how much room they take up.

SQL Server keeps up to 6 error log files around by default. You can easily change this. Open up your copy of SSMS and:

  1. Expand the “Management” folder.
  2. Right click on “SQL Server Logs”
  3. Select “Configure”
  4. Check the box “Limit the number of error log files before they are recycled”
  5. Pick some value to put in the “Maximum number of error log failes” box
  6. Click “OK”

It’s just that easy! Admittedly, you have to do this on every SQL Server that you have, so you might just want to click the “Script” button so you can push the script to multiple SQL Servers.

Automatically Rotating the SQL Server Error Log

You can set up SQL Server to automatically rotate your error logs. This is the easiest part of this blog post, apart from closing the window.

To cycle error logs on a regular basis, restart your SQL Server nightly.

Only joking.

You can set up a SQL Agent job with a T-SQL step. All it has to do is EXEC sp_cycle_errorlog. Schedule the SQL Agent job to run as frequently as you’d like and you’re good to go. The upside of this approach is that it’s automatic and the SQL Server error logs will be more granular, making it easier to find the error messages you’re looking for.

It’s Just That Easy!

Cycling the SQL Server error log is easy – you just need a regularly scheduled agent job. Rotating the logs makes it easier to find error messages. Let’s face it – you’re only looking for error messages when there’s a problem. That’s all there is to rotating the error logs.


Window Functions and Cruel Defaults

SQL Server, T-SQL
5 Comments

My First Post Here…

Well, my first technical post, was about how the default index creation method is OFFLINE. If you want that sweet, sweet Enterpri$e Edition ONLINE goodness, you need to specify it. It’s been a while since that one; almost six months to the day. So here’s another one!

But Window Functions Are Awesome

Heck yeah they are. And how. Boy howdy. Etc. You get the point. I’m enthusiastic. What can be cruel about them? Glad you asked!

Window Functions, according to the almighty ANSI Standard, have two ways of framing data: RANGE and ROWS. Without getting into the implementation differences between the ANSI Standard and Microsoft’s versions, or any performance differences between the two, there’s a funny difference in how they handle aggregations when ordered by non-unique values. A simple example using the Stack Overflow database follows.

For the month of August, Year of Our Codd 2008, we’re getting a running total of the score for posts by UserId 1. Who is UserId 1? I’ll never tell. But back to the syntax! In the first SUM, we’re not specifying anything, for the next two we’re specifying RANGE and then ROWS. Why? REASONS! And why am I casting the CreateDate column as a date? MORE REASONS!

Before you scroll down, think for a second:

If I don’t specify RANGE or ROWS, which will SQL Server use?
If I left the CreateDate column as DATETIME, what eff aff difference would it make to the output?

Do you see a pattern forming here?

OH MY GOD IT WORKED
OH MY GOD IT WORKED

When we don’t specify RANGE or ROWS, well, SQL Server is nice enough to pick RANGE for us. “Nice”.

Whose fault? Default!
Whose fault? Default!

Deep breaths, Erik. Deep breaths.

You should also notice the difference in how each different method aggregates data. When the ordering column has duplicates, RANGE, and by extension, the default method, will SUM all the values for that group at once. When ROWS is specified as the framing method, you see the running total that most people are after.

Make project managers happy!
Make project managers happy!

And, of course, if all the values were unique, they’d do the same thing.

Back for a day
Back for a day

Wrap. It. Up.

This one is pretty self explanatory. If you’re lucky enough to be on SQL Server 2012 or greater, and you’re using Window Functions to their full T-SQL potential, it’s was easier to calculate running totals. Just be careful how you write your code.

If you like this sort of stuff, Check out Doug’s new video series, T-SQL Level Up. There are next to zero fart jokes in it.


Announcing Our 2016 In-Person Training Class Schedule

SQL Server
7 Comments
Jeremiah teaching in Portland
Jeremiah teaching in Portland

We just finished up the last of our 2015 training classes, and the reviews have been glowing:

“I have attended many training classes in my 19 years as a DBA, including Oracle and SQL Server. This is the first class where 75+% of the information I learned is applicable to my current work environment.” – Christina Z.

“I thought the class was much more useful than the Microsoft Official Curriculum. Those classes seem to teach to the book and instructors often can’t answer questions that aren’t included in the curriculum. You guys have real-world experience that you can share with the students. Very valuable!” – Kris C.

“They’re really best of the best on the market. And always open to QA sessions. And they asked do you have any questions? And ALWAYS have answers!!!!” – Vlad B.

And now, registration is open for next year’s training class lineup. Drum roll please:

Advanced Querying and Indexing – 5 days, $3,995

  • Jan 11-15, Newark
  • August 8-12, Portland

SQL Server Performance Troubleshooting – 4 days now expanded to 5 days, $3,995:

  • February 22-26, San Diego
  • April 11-15, Newark
  • June 6-10, Chicago
  • August 15-19, Portland
  • December 5-9, Philadelphia

The Senior DBA Class of 2016 – 5 days, $3,995

  • March 7-11, Chicago
  • May 2-6, Denver
  • August 1-5, Philadelphia

We’ve been updating each class to reflect new technologies and techniques, and we’re excited to share what we’ve been teaching our clients. And of course, if you’d like to bring one of us onsite to teach a custom class lineup, check out our training catalog and email us.


Need to Migrate or Upgrade SQL Server? Register for our upcoming webcast!

SQL Server
13 Comments

KendraLittle_BioDrawing_CroppedChange is exciting, and a little scary, too. If you’re looking to upgrade or migrate your SQL Server, head on over to our events page and get registered for our upcoming free webcast on Thursday, Oct 15 at 10:00AM Central, 11:00AM Eastern.

SQL Server Migration Checklist (Sponsored by Veeam)

It’s time to upgrade your SQL Server! But do you know exactly what you need to do? Join this free webinar with Microsoft Certified Master Kendra Little to get her checklist to make your migration go smoothly. You’ll learn what you need to script and document from your current instance, which settings you should change after your migration, required tests for new installations, and better alternatives to in-place upgrades. Whether your SQL Server 2005 instance is hitting end of life or you’re planning an upgrade to the latest and greatest, this migration checklist will save you time and frustration. Register now.

Missed the Webcast, but want the Migration Checklist?

Download the SQL Server Migration Checklist eBook as part of our free First Responder Kit.


Announcing: Level Up Your T-SQL

SQL Server
16 Comments

You spend at least an hour or two each day writing T-SQL code. You have a pretty good hunch that it’s not as fast or crisp as it should be, and you wonder if you’re missing a few techniques. You’ve heard about date tables and windowing functions, but you’re just not comfortable with ’em yet.

I’m Doug Lane of Brent Ozar Unlimited, and my new online training class is for you. It’s loaded with T-SQL goodies like using computed columns, how to replace cursors, and more. Here’s a sneak preview:

It’s unlike any T-SQL training you’ve ever seen (seriously!), and it’s totally free. I’d love to hear what you think.

Our customers, who got free access to it as a thank-you, have already started leaving reviews:

“Great job on delivering information with a wink and a nod. It really held my interest.” – Debby

“Doug is an exceptional speaker, and uses humour in effective ways to convey difficult concepts. I learnt a thing or two from this course.” – Randolph

“If only l had seen this course when l started out my SQL journey! I love the teaching style it works well for me. Then there are those simple time saving tips slipped in just at the right time. The analogy about banking the coins, genius wish l had thought of it! Teaching pace it timed perfectly. Overall looking forward to seeing more Robert

“This is perhaps the nerdiest thing I’ve seen all year.” – Wulfgar

“Great starter for thinking set-based!” – Gustavo

“I loved the Set Based sections with the examples of the cursors and how you could change the code to make them set based operations. But I think my favorite part was the windowing functions. Now I have good examples of how they work and when they are a good fit.” – Colin

“This course is funny and filled with a lot of good information. A great recap for any DBA. And a gold mine for anybody less experimented with coding T-SQL. The Windowing functions part is especially helpful. I suggest this course to anybody writing T-SQL.” – Benoit


What’s More Popular: SQL Server 2014, or SQL Server 2005?

SQL Server
73 Comments

Sure, you’d much rather work with SQL Server 2014, but what’s more prevalent out in the real world? At Dell DBA Days, I saw a chart that shocked me:

SQL Server version popularity
SQL Server version popularity as of Sept 2015

That chart shows the number of servers running Dell Spotlight Essentials, a free SQL Server monitoring tool. Note that SQL Server 2014 has 4% of the population, about 1/4 as much as SQL Server 2005.

But the terrifying part: for every 2 SQL Server 2014 instances, there’s one SQL Server 2000 instance still kicking around! That’s not exactly a rapid adoption rate.

I wonder why we aren’t we upgrading our SQL Server 2000 instances? (And I’m not pointing the figure at you – it’s likely the business that’s making you keep it around.)


Filtered Indexes and IS NOT NULL

Indexing, SQL Server
23 Comments

Filtered indexes can be tricky. Just getting your queries to use the filtered index can be a real pain. Parameterization may mean it’s “unsafe” to use the filtered index. The optimizer might want the filtered column in your key or include column list when it doesn’t seem like it should have to be there. The weather might be cloudy.

But there’s one type of filtered index that everyone can love for a couple different reasons: IS NOT NULL.

“IS NOT NULL” filter for a selective query…

Here’s an example index. We’re using the StackOverflow sample database and creating the index only on Posts which are closed (a small subset):

Here’s a query looking for Posts with a ClosedDate in a given range. Note that the query does NOT say “ClosedDate is NOT NULL”, it’s just specifying a value range:

We give the query a run and look at the plan….

Woooo, it matches my index!

The highlighted index is ix_Posts_Score_ClosedDate_INCLUDES_FILTERED
The highlighted index is ix_Posts_Score_ClosedDate_INCLUDES_FILTERED

And now for my next trick… what if you need to guarantee uniqueness for a column that allows NULLS?

We’re entering controversial territory here, so I’m going to be careful. SQL Server treats NULL as a value. This is a really big deal to some people, and I totally understand if you want to vent in the comments about how that’s a terrible thing and it shouldn’t be that way, and SQL Server stole your pickup truck. But it’s the SQL Server we live in.

Treating NULLs as a value means that I can’t create a unique index or a unique constraint on a column that allows NULLs if it has more than one row with NULL in it. More than one NULL means I have duplicates.

A filtered unique index can get you around the problem, like this:

Yay for indexes!

We’ve got tons of material on indexes, start reading more over here.


Getting Started with Diskspd

SQL Server
62 Comments

Diskspeed, or diskspd.exe, is Microsoft’s replacement for SQLIO. While I’m not going to replace our SQLIO tutorial, you can use the information in here to replicate the same type of tests on your systems to get the information you need. During the Dell DBA Days, Doug and I used diskspd as one of our techniques for getting a baseline of raw performance. We wanted to get an idea of how fast the servers and storage before running SQL Server specific tests.

How do I get diskspd?

You can download diskspd directly from Microsoft – Diskspd, a Robust Storage Testing Tool, Now Publically Available. That page has a download link as well as a sample command.

The upside is that diskspd is a fully self-contained download. You don’t need Java, .NET, or anything else installed to run it. Apart from Windows – you’ll still need Windows.

How do I use diskspd?

With the command line, of course!

In all seriousness, although diskspd is the engine behind Crystal Disk Mark, it stands on its own as a separate tool. Download the executable and unzip it to an appropriate folder. There are going to be three sub-folders:

  • amd64fre – this is what you need if you have a 64-bit SQL Server
  • armfre
  • x86fre

I took the diskspd.exe file from the appropriate folder and dumped it in C:\diskspd so I could easily re-run the command. Let’s fire up a command prompt and try it out.

Here’s a sample that we ran: diskspd.exe -b2M -d60 -o32 -h -L -t56 -W -w0 O:\temp\test.dat > output.txt

Breaking it down:

  • -b2M – Use a 2 MB I/O size. For this test, we wanted to simulate SQL Server read ahead performance.
  • -d60 – Run for 60 seconds. I’m lazy and don’t like to wait.
  • -o32 – 32 outstanding I/O requests. This is your queue depth 32.
  • -h – This disables both hardware and software buffering. SQL Server does this, so we want to be the same.
  • -L – Grab disk latency numbers. You know, just because.
  • -t56 – Use 56 threads per file. We only have one file, but we have 56 cores.
  • -W – Warm up the workload for 5 seconds.
  • -w0 – No writes, just reads. We’re pretending this is a data warehouse.
  • D:\temp\test.dat – our sample file. You could create a sample file (or files) by runningdiskspd with the -c<size> flag.
  • > output.txt – I used output redirection to send the output to a file instead of my screen.

How do I read diskspd results?

You’re going to get a lot of information back from this command. You’re going to want to close the window and back away quickly. Don’t. This is good stuff, I promise.

The first thing you’ll see is a recap of the command line you used. Then you’ll immediately see a summary of the commands:

That’s a lot easier than trying to read a set of command line flags. Six months from now, I can review older runs of diskspd and understand the options that I used. diskspd is already winning over sqlio.

Next up, you’ll see a summary of CPU information. This information will help you understand if your storage test is CPU bottlenecked – if you know the storage has more throughput or IOPS capability, but your tests won’t go faster, you should check for bottlencks. The last line of this section (and every section) will provide an average across all CPUs/threads/whatevers.

After the CPU round up, you’ll see a total I/O round up – this includes both reads and writes.

Look at all of those bytes!

If the I/O numbers initially seem small, remember that the data is split up per worker thread. Scroll down to the bottom of each section (total, reads, writes) and look at the total line. This rounds up the overall volume of data you’ve collected. The I/Os are recorded in whateverunit of measure you supplied. In our case, the I/Os are 2MB I/Os.

Important Sidebar Your storage vendor probably records their I/O numbers in a smaller I/O measurement, so make sure you do some rough translation if you want to compare your numbers to the advertised numbers. For more discussion, visit IOPS are a scam.

Finally, latency! Everybody wants to know about latency – this is part of what the end users are complaining about when they say “SQL Server is slow, fix it!”

This table keeps the min, max, and a variety of percentiles about how the storage performed while you were beating on. This information is just as helpful as the raw throughput data – under load your storage may have increased latencies. It’s important to know the storage will behave and respond under load.

How often should I use diskspd?

Ideally, you should use diskspd whenever you’re setting up new storage or a new server. In addition, you should take the time to use diskspd when you make big changes to storage – use diskspd to verify that your changes are actually an improvement. No, diskspd doesn’t include the work that SQL Server does, but it does show you how your storage can perform. Use it to make sure you’re getting the performance you’ve been promised by your storage vendor.


Consulting Lines: “Let’s put that in the parking lot.”

Consulting, Consulting Lines
8 Comments

There’s a fine art to running a productive meeting, keeping the discussion focused and scoping things tight to meet your scheduled finish time. Today’s consulting lines post is about keeping people happy while still finishing meetings on time.

Let’s join a troubleshooting session where I’ve been brought in to help a client whose AlwaysOn Availability Groups are failing over randomly in the middle of the day.

The Conversation:

Me: “According to the network control panel, this server has two Ethernet ports, but only one of them is plugged in?”

Sarah the Sysadmin: “Yeah. All our physical servers are set up that way, and I’m not happy about it either. We’re going to be virtualizing these servers early next year, and I’ve got a preliminary plan for the networking switches that I can show you. I can just present one network card to the guest and do the teaming at the host layer, right?”

Me: “That’s a great question. I’m going to set up a section of the whiteboard over here called the Parking Lot, and I’m going to write that down.”

What That Line Does

It conveys that the question is indeed a good one, and you’re qualified to answer it, but that the answer is going to take more than a minute or two.

It also sets up a normal protocol that can help you through the rest of the meeting – and heck, even the client relationship. One of my long-term clients got so trained that when I walked into their conference room, they’d already white boarded out the day’s agenda ahead of time – and set up a parking lot with a few items!

If you’re working remotely, you can use a shared Google Drive document to track the meeting’s agenda, notes, resources, and parking lot. (Just be careful with the Google permissions – those get kinda tricky when you’re working with multiple clients.)

What Happens Next

I wanna add this to my parking lot too.
I wanna add this to my parking lot too.

Sarah: “But this will only take a minute – ”

Me: “Are you willing to virtualize those servers this weekend?”

Sarah: “Oh definitely not, we have to buy the hosts and – ”

Me: “Can we just leave the failover problems as-is, and wait for the virtualization replacements?”

Mark the Manager: “No, we need the failovers fixed now, like yesterday.”

Me: “OK, so here’s the deal. I definitely want to help you configure the virtualization project, and the answer involves sketching out whether you’re using iSCSI or not. My contract for today’s engagement depends on me solving this failover problem, so I kinda gotta focus on that for now. If I don’t fix this, the executives won’t pay my bill, and my wife is getting tired of ketchup sandwiches, ha ha ho ho. So let’s put this in the parking lot, and we can talk about it as soon as we’ve got the root cause of the failover identified. Is that fair?”

For more meeting tactics, check out my consulting lines.


Performing Your Own SQL Server Triage

SQL Server
6 Comments

Our new Triage Specialist will be using tools, forms, and methodologies that we build for our SQL Critical Care® clients, but we also make a lot of those tools available to the public for free in our First Responder Kit.

Here’s how to do your own quick health assessment for free:

First, start your health check with sp_Blitz®. It’s a stored procedure that gives you a prioritized list of problems on your SQL Server. If the databases are all third party apps that you can’t control, use the @CheckUserDatabaseObjects = 0 parameter to focus the results on the things you can change. sp_Blitz® works on SQL Server 2005 and newer, but it doesn’t work on databases in SQL Server 2000 compatibility mode.

If you don’t think one of the resulting rows is important, or if you don’t understand the warning, copy the contents of the URL column into your browser and spend a few minutes reading the details. For example, at least once a month, we run across a server having performance problems, and it turns out not all of the CPU and memory is actually available to SQL Server. Sure enough, when we look at sp_Blitz®, it warns about CPU schedulers being offline, and the admin says something to the effect of, “Oh, I saw that in sp_Blitz®’s output, but I wasn’t really sure what it meant because I didn’t read the URL.”

Next, check your server’s bottlenecks with sp_BlitzFirst®. This stored proc was designed for live real-time performance troubleshooting, but it has another cool use. Use the @Seconds = 0, @ExpertMode = 1 parameters, and the second result set will show you your server’s primary wait stats since SQL Server was restarted (or since someone cleared the wait stats.) This helps guide you toward the type of performance bottleneck you’re troubleshooting – is it a CPU bottleneck, storage issue, or locking?

Armed with that knowledge, check your top resource-intensive queries with sp_BlitzCache®. Once you know the kind of bottleneck you’re looking for, use the @sort_order parameters to get to the right queries:

  • Looking for high CPU consumers? @sort_order = ‘cpu’
  • Tracking down the source of PAGEIOLATCH waits due to queries dragging a lot of data back from disk? @sort_order = ‘reads’
  • Wondering who’s getting blocked for long periods of time? Try @sort_order = ‘duration’

Then make the queries more efficient with sp_BlitzIndex®. Now that you know the worst queries and the database they’re in, run sp_BlitzIndex® in that database and get a psychological profile of your indexes.

  • Dastardly deadlocks? Look for the Aggressive Indexes warnings about high lock waits on an index.
  • Slow selects? Check out the high-value missing index warnings.
  • Intolerable inserts? Read the Hoarder warnings about tables that have a high number of nonclustered indexes that aren’t getting used.

We slather trademarks all over these tools because we’re really proud of ’em. We use them every single day in our consulting work, and we want you to use them in your triage work too. You might even wanna just practice using ’em in case we ever ask you to use ’em during our job interviews. (That’s a hint.)


Why RPO and RTO Are Actually Performance Metrics Too

Most companies come to us saying, “The SQL Server isn’t fast enough. Help us make it go faster.”

They’re kinda surprised when one of the first things we fill out together is a variation of our High Availability and Disaster Recovery Planning Worksheet:

Download the full PDF in our First Responder Kit
Download the full PDF in our First Responder Kit

They say things like, “Wait, I’m having a performance problem, not an availability problem.”

But as we start to look at the SQL Server, we often find a few disturbing truths:

  • The admins have stopped doing transaction log backups and DBCC CHECKDB because the server can’t handle the performance hit
  • Management thinks the database can’t lose any data because communication wasn’t clear between admins and managers
  • The server isn’t even remotely fast enough to start handling data protection, let alone the end user query requirements

I know you think I’m making this up. I know you find this hard to believe, dear reader, but not everyone is a diligent DBA like you. Not everyone has their RPO and RTO goals in writing, tests their restores, and patches their SQL Server to prevent known corruption bugs. I hope you’re sitting down when you read this, but there are some database administrators out there who, when given the choice between index rebuilds and transaction log backups, will choose the former on a mission-critical 24/7 system.

I’m sure that would never be you, dear reader, but these database administrators are out there, and they’re exactly the kinds of shops who end up calling us for help.

Then the fun part is that once we establish what the business really wants in terms of data safety, it often dictates a new server – say, moving from a single standalone VM with no HA/DR up to a full-blown failover cluster. And in the process of sketching out that new cluster, we can solve the performance problems at the same time without any changes to their application. (Throwing hardware isn’t the right answer all the time – but when you need to add automatic failover protection, it’s the only answer.)

That’s why we start our SQL Critical Care® by talking about what the business needs and what the system is really delivering, and get everyone on the same page as to what needs to happen next.


Scaling Up Our SQL Critical Care®

SQL Server
7 Comments

Since we’re hiring again, it’s a good time to explain what we do and how it’s evolved over the last four years.

When your SQL Server’s performance or reliability is causing you business pain, and you can’t get the relief you want, you call us for a SQL Critical Care®. We use specialized tools we’ve built to quickly get to the root cause. Then we explain it to you in clear, friendly terms, and train you how to get permanent pain relief.

Notice how we keep using medical terms? That’s no coincidence – we’re very much like a doctor’s office. Over the course of performing hundreds of these, and because the waiting room keeps filling up, we’ve scaled this to where we treat it like a hospital.

You can tell the drugs kicked in because I'm smiling.
You can tell the drugs kicked in because I’m smiling.

Remember that time I broke my arm saving a nun from a car wreck carrying a flat panel monitor? I went into the hospital, the triage nurse made sure I wasn’t having a heart attack, then got me into radiology for scans, then a doctor reviewed the situation, and he brought in an orthopedic surgeon for a consult on whether they should operate. The hospital had all of these experts available, and they rotated in and out of the room based on my needs.

Because of our scale, we’re able to bring that same approach to SQL Server pain relief.

First, a Triage Specialist reviews your RPO and RTO objectives, learns how you use SQL Server, collects diagnostic information, and prescribes changes to avoid data loss. Then, based on what the Triage Specialist finds, they bring in different specialists. The situation calls for plan guides? You’ll get a T-SQL surgeon who’s used that unusual trick before. Need pain relief for an AG in EC2 that randomly fails over? You’ll be able to work with an AlwaysOnologist who’s built up specialized tools to diagnose it.

We couldn’t use this approach when we only had a few consultants, but now that we’re doing so many of these, fun options open up.