Cardinality Estimation and Row Estimates

How SQL Server estimates rows and how estimate errors affect plan choices.

60 associated posts57 primary posts

Performance Tuning

“I’m getting index seeks. Why are my row estimates still wrong?”

If you've got good indexes to support your query, and statistics to help SQL Server guess how many rows will come back, how can SQL Server still come up with terribly incorrect row estimates? To demonstrate, I'll use the 2018-06 version of the Stack Overflow database, but any recent version will work as long as…

Read more about “I’m getting index seeks. Why are my row estimates still wrong?” 11 comments — Join the discussion
Performance Tuning

Execution Plans Don’t Have the Yellow Bang They Really Need.

When SQL Server is purely making an estimate up out of thin air, with no freakin' idea what the real answer is, it doesn't give you any kind of warning. It just produces an estimate that looks scientifically accurate - until you know how it's actually getting calculated. Let's ask SQL Server how many users have…

Read more about Execution Plans Don’t Have the Yellow Bang They Really Need. 12 comments — Join the discussion

How Bad Statistics Cause Bad SQL Server Query Performance

SQL Server uses statistics to guess how many rows will match what your query is looking for. When it guesses too low, your queries will perform poorly because they won't get enough memory or CPU resources. When it guesses too high, SQL Server will allocate too much memory and your Page Life Expectancy (PLE) will nosedive.

Read more about How Bad Statistics Cause Bad SQL Server Query Performance 3 comments — Join the discussion
Performance Tuning

Date Tables are Great for Users, but Not So Great for Performance

Date tables help users filter data based on day of week, holiday, this year vs last year, and other kinds of filters that business users usually wanna add to their reports. If you haven't used a date table before, here are a couple of primers on how to create one and use it:

Creating a date dimension table by Aaron Bertrand
How to create a date_calendar table by Sean Smith

Read more about Date Tables are Great for Users, but Not So Great for Performance 34 comments — Join the discussion

The 201 Buckets Problem, Part 2: How Bad Estimates Backfire As Your Data Grows

In the last post, I talked about how we don't get accurate estimates because SQL Server's statistics only have up to 201 buckets in the histogram. It didn't matter much in that post, though, because we were using the small StackOverflow2010 database. But what happens as our data grows? Let's move to a newer Stack…

Read more about The 201 Buckets Problem, Part 2: How Bad Estimates Backfire As Your Data Grows 14 comments — Join the discussion

The 201 Buckets Problem, Part 1: Why You Still Don’t Get Accurate Estimates

I'll start with the smallest Stack Overflow 2010 database and set up an index on Location: [crayon-6a6ece74267a9063275346/] There are about 300,000 Users - not a lot, but enough that it will start to give SQL Server some estimation problems: When you create an index, SQL Server automatically creates a statistic with the same name. A…

Read more about The 201 Buckets Problem, Part 1: Why You Still Don’t Get Accurate Estimates 7 comments — Join the discussion
Performance Tuning

How to Get Better Estimates for Modification Queries

When you're doing DUI operations against tables with millions of rows, you have to be really careful about SQL Server's estimates. Ideally, you want your delete/update/insert (what - what'd you think I meant?) queries to be as simple as possible - even a simple join can cause SQL Server to do wildly, wildly incorrect estimates, which affects memory grants, parallelism, wide vs narrow plans, and more.

Read more about How to Get Better Estimates for Modification Queries 4 comments — Join the discussion
Performance Tuning

WHERE GETDATE() BETWEEN StartDate AND COALESCE(CancelDate, EndDate) Is Even Harder to Tune.

In my last post, we started with a memberships table, and each membership had start & end dates. I'm going to create the table and populate it with everyone having an active membership - their StartDate is the same as their Stack Overflow account creation date, and their EndDate is around a year or two…

Read more about WHERE GETDATE() BETWEEN StartDate AND COALESCE(CancelDate, EndDate) Is Even Harder to Tune. 8 comments — Join the discussion
T-SQL & Development

How to Remove Times from Dates in SQL Server

Say that you've got a table with a datetime column in it, like the LastAccessDate column in the Stack Overflow Users table:

And let's say you wanna find the users who last accessed the site on September 9, 2018 - regardless of the time. Here are a few ways to do it:
[crayon-6a6ece7427aea919744829/]
Here are their actual execution plans. I'm using SQL Server 2019, with 2019 compatibility level, and the 50GB StackOverflow2013 database.

Read more about How to Remove Times from Dates in SQL Server 34 comments — Join the discussion

How to Think Like the SQL Server Engine: When Statistics Don’t Help

In our last episode, we saw how SQL Server estimates row count using statistics. Let's write two slightly different versions of our query - this time, only looking for a single day's worth of users - and see how its estimations go: [crayon-6a6ece7428516980099053/] Both of those queries are theoretically identical in that they accomplish the…

Read more about How to Think Like the SQL Server Engine: When Statistics Don’t Help 16 comments — Join the discussion

How to Think Like the SQL Server Engine: Using Statistics to Build Query Plans

In our last episode, SQL Server was picking between index seeks and table scans, dancing along the tipping point to figure out which one would be more efficient for a query.

One of my favorite things about SQL Server is the sheer number of things it has to consider when building a query plan. It has to think about:

Read more about How to Think Like the SQL Server Engine: Using Statistics to Build Query Plans 8 comments — Join the discussion
Performance Tuning

What’s New in SQL Server 2019: Faster Table Variables (And New Parameter Sniffing Issues)

For over a decade, SQL Server's handling of table variables has been legendarily bad. I've long used this Stack Overflow query from Sam Saffron to illustrate terrible cardinality estimation:
[crayon-6a6ece7429d22147374221/]
It puts a bunch of data into a table variable, and then queries that same table variable. On the small StackOverflow2010 database, it takes almost a full minute, and does almost a million logical reads. Here's the plan:

Read more about What’s New in SQL Server 2019: Faster Table Variables (And New Parameter Sniffing Issues) 17 comments — Join the discussion
Performance Tuning

A Simple Stored Procedure Pattern To Avoid

Get Yourself Together
This is one of the most common patterns that I see in stored procedures. I'm going to simplify things a bit, but hopefully you'll get enough to identify it when you're looking at your own code.

Here's the stored procedure:
[crayon-6a6ece742a336268135186/]
There's a lot of perceived cleverness in here.

Read more about A Simple Stored Procedure Pattern To Avoid 15 comments — Join the discussion
Performance Tuning

Should You Use the New Compatibility Modes and Cardinality Estimator?

For years, when you right-clicked on a database and click Properties, the "Compatibility Level" dropdown was like that light switch in the hallway: You would flip it back and forth, and you didn't really understand what it was doing. Lights didn't go on and off. So after flipping it back and forth a few times,…

Read more about Should You Use the New Compatibility Modes and Cardinality Estimator? 13 comments — Join the discussion