Blog

T-SQL Tuesday: Cool Query Transforms, Cool Query Plans #tsqltuesday

Trick Shots



Query tuning is hard work, especially when queries run for a long time and you have to test various changes trying to get it down to a reasonable runtime.

There are, of course, things you pick up intuitively over time, and figuring out where problems in actual execution plans has gotten easier with operator runtimes.

Beyond basic query tuning intuition comes the really creative stuff. The stuff you’re amazed anyone ever thought of.

I’m going to show you some examples of that.

Cross Tops


Let’s say you want to find the top 1000 rows for a few whatevers. In my case, whatever are users, and the table is Posts.

We’ll start by creating an index to support our query:

CREATE INDEX 
    p 
ON dbo.Posts
    (OwnerUserId, CreationDate DESC)
WITH
    (SORT_IN_TEMPDB = ON, DATA_COMPRESSION = PAGE);

The most intuitive way to write the query looks like this:

SELECT TOP (1000)
    p.*
FROM dbo.Posts AS p
WHERE p.OwnerUserId IN (22656, 29407, 157882)
ORDER BY 
    p.CreationDate DESC;

Because of my super professional indexing skills, the query plan looks like this:

i am iron man?

Is this good? Bad? Good enough? Well, it takes 328ms, and asks for memory to sort data. It’s a little bit weird that we need to sort anything, because our index has CreationDate in order, and we’re doing what would appear to be equality searches on OwnerUserId.

One query pattern I’ve seen and written copied on multiple occasions is something like this:

SELECT TOP (1000)
    p.*
FROM 
(
    VALUES 
        (22656), 
        (29407), 
        (157882)
) AS x (x)
CROSS APPLY
(
    SELECT TOP (1000)
        p.*
    FROM dbo.Posts AS p
    WHERE p.OwnerUserId = x.x
    ORDER BY p.CreationDate DESC
) AS p
ORDER BY 
    p.CreationDate DESC;

It’s a little more complicated, but we use the VALUES clause to list our literals, and CROSS APPLY them with the Posts table.

Is it better? Best? Finally good enough?

woogy

Well, it finishes a lot faster, but it still results in a sort, and a ~3x increase in the memory grant, up to 1GB. A fascinating conundrum.

Unionville


A query pattern that really baked my noodle like stoner casserole is this one:

SELECT TOP (1000)
    p.*
FROM dbo.Posts AS p
WHERE p.OwnerUserId IN (SELECT 22656 UNION SELECT 29407 UNION SELECT 157882)
ORDER BY 
    p.CreationDate DESC;

Rather than just listing values by comma, or using the VALUES clause, we’re selecting each value UNIONed (not UNION ALLed) in the IN clause.

How do we do here? Good? Done? Finally?

caption me please i beg of you

Well, the query plan is a hell of a lot bigger, but it finishes and doesn’t ask for any memory. The order is preserved by Merge Concatenation.

Like I said: casserole.

Paster Blaster


One of the very first demos I saw that made me feel totally out of my depth in T-SQL is this one.

Seriously. Watch the video to get a full explanation for the query and why it’s written this way.

Because the code is hard to read and the video is sort of blurry, I’m going to reproduce it here using the same basic idea in the Stack Overflow database:

First, some supportive indexes:

CREATE INDEX 
    p 
ON dbo.Posts
    (OwnerUserId) 
INCLUDE
    (Score)
WITH
    (SORT_IN_TEMPDB = ON, DATA_COMPRESSION = PAGE);


CREATE INDEX 
    c 
ON dbo.Comments
    (UserId) 
INCLUDE
    (Score)
WITH
    (SORT_IN_TEMPDB = ON, DATA_COMPRESSION = PAGE);

And now, the reproduced query:

SELECT TOP (1000) 
    u.DisplayName, 
    ca.Score
FROM dbo.Users AS u
CROSS APPLY 
(
    SELECT 
        Score = SUM(x.Score)
    FROM 
    (
        SELECT 
            c.Score
        FROM dbo.Comments AS c
        WHERE c.UserId = u.Id
        
        UNION ALL
        
        SELECT 
            p.*
        FROM 
        (
            SELECT TOP (1) 
                f = 1
            WHERE u.CreationDate >= '2016-01-01'
            AND   u.Reputation = 10
        ) AS f
        CROSS APPLY
        (
            SELECT 
                p.Score
            FROM dbo.Posts AS p
            WHERE p.OwnerUserId = u.Id
        ) AS p    
    ) AS x
) AS ca
ORDER BY 
    u.Reputation DESC;

And the reproduced query plan:

going yard

Seriously. There’s a SELECT TOP (1) with no FROM clause, and a WHERE clause.

I can’t imagine how much alcohol it would take to figure that out.

Thanks for reading!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

What Parameter Sniffing Looks Like in SQL Server’s Query Store

What Parameter Sniffing Looks Like in SQL Server’s Query Store


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

Why SQL Server’s ROWLOCK Hint Doesn’t Always Just Lock Rows

Why SQL Server’s ROWLOCK Hint Doesn’t Always Just Lock Rows


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

How To Fix Blocking In SQL Server With Better Indexes

How To Fix Blocking In SQL Server With Better Indexes


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

The Best Way To Troubleshoot Slow SQL Server Queries

The Best Way To Troubleshoot Slow SQL Server Queries


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

T-SQL Tuesday: Code That Made You Feel A Way

Logo


First, this post needs to have the T-SQL Tuesday logo in it, so sayeth the rules. Here’s that.

This month’s topic challenges you to think back to the last time you saw code that made you feel a thing. Hopefully a positive thing.

I’m not a thesaurus, so the list isn’t exhaustive, but think along the lines of: surprise, awe, inspiration, excitement.

Or maybe it was just code that sort of sunk its teeth into you and made you want to learn a whole lot more.

 

This won’t be my submission, but I think a great example is a piece of query tuning magic by Paul White. It was one of the first articles I ever read as a young SQL Developer.

It was one of many lightbulb moments (and, crap, I should have said lightbulb moment up there when I was telling you what kind of code I want you to think about) that I’ve had in my career.

The only rule I have is (outside of the normal T-SQL Tuesday rules) is that it can’t be your own code.

It should also probably be code that you won’t get sued for showing or talking about. Please be diligent in abiding by copyrights.

Other than that, it’s the normal pack of rabbits: submissions have to be posted next Tuesday, the 11th of July.

I’ll post a roundup after I’ve had time to gather all the links and write something sufficiently witty about each one of them.

If you feel the need to go negative, make sure it’s about something that no sane or rational person could disagree with, like comma placement, whitespace, indentation, capitalization, line endings, naming conventions, or aliases.

But especially if table aliases should be capitalized. We all know they shouldn’t.

Thanks for reading!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

How I Use sp_BlitzLock To Investigate SQL Server Deadlocks

How I Use sp_BlitzLock To Investigate SQL Server Deadlocks


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

How I Use sp_BlitzCache To Find Poor Performing SQL Server Queries To Tune

How I Use sp_BlitzCache To Find Poor Performing SQL Server Queries To Tune


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

How I Use sp_BlitzIndex To Find Indexing Problems In SQL Server Databases

How I Use sp_BlitzIndex To Find Indexing Problems In SQL Server Databases


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.

How I Use sp_BlitzFirst To Profile SQL Server

How I Use sp_BlitzFirst To Profile SQL Server


Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. You can also get a quick, low cost health check with no phone time required.