Query Plan Patterns For Windowing Functions: Row Mode vs Batch Mode

Query Plan Patterns For Windowing Functions: Row Mode vs Batch Mode



Thanks for watching!

Video Summary

In this video, I delve into the intricacies of query execution plans when window functions are involved, breaking it down into three parts to ensure that the content is digestible and comprehensive. Starting off by discussing the differences between row mode and batch mode for these queries, I highlight how critical it is to use batch mode for optimal performance, especially with large datasets. I also explore the impact of having or not having a `PARTITION BY` clause in your windowing functions, noting that the absence of this clause can significantly alter the query plan’s parallelism and execution efficiency. Throughout the video, I share practical insights on how to recognize these patterns and optimize queries for better performance, emphasizing the importance of proper indexing and predicate usage.

Full Transcript

Erik Darling here with Darling Data. Feeling real happy at the moment. Extra happy. Probably the happiest I’ve been in, I don’t know, 37, 38 years? No particular reason. Feeling kind of peppy at the moment. And so this is going to be split up into three parts, not six parts, just the last part. three. One, three or the other. Only three, not double three. Because the material’s a little too dense for a single video. I don’t think anyone would stick around for the whole thing. So we’re breaking this one up into three parts. This is going to be talking about query execution plans when window functions are involved. Because it struck me when I was recording something a while back. And I was talking about how I’ve, over time, learned how to predict what will be in a query by looking at the query plan. And I think someone commented that that would be a cool thing to talk about. So I’m going to talk a little bit about query plan patterns for different queries that I can sort of recognize. There’s going to be a bunch of those videos, but there’s three on windowing functions. There’s just about enough to talk about with windowing functions that I think it is worthwhile. There are essentially three different kinds of windowing functions. There’s like the ranking ones, so like row number, rank, dense rank. There’s aggregates, like sum and count and average. And then there’s the analytical ones, like cum dist and whatever discrete something. I can’t keep track of all those things. I don’t think I’ve ever really used them. I guess Entile would be in there. Entile is the only weird one that I’ve used pretty regularly. I dig Entile. I think Entile’s a cool cat. If you don’t use Entile, I don’t know, you should. Team Entile over here with Darling Data. Anyway, what was I going to say? Oh yeah, some some crap that apparently is useful because since I started saying this stuff at the beginning of the videos, things have been picking up. So good job, everyone, for paying attention early on. If you like this content and you feel like it is worth like four bucks a month, you can sign up for a membership to my channel. That’d be cool. If you don’t have the extra four bucks a month, if that’s going into your Happy Meal fund, Lord knows inflation has really messed with the prices of Happy Meals. Maybe that’s why I’m happy. I started thinking about Happy Meals and that brought me back to my youth. Never can tell. Other ways to show your love, support, and enduring allegiance to Darling Data. Humble leader. Likes, comments, subscribes, all nice things that you can do.

If you are in a real pickle and you need SQL Server consulting, I am available to do just about anything that doesn’t involve replication. These are the things that I excel at. I don’t use Excel much, but I do excel at these things. And what do you call it? If you need anything outside of this sort of stuff, well, my rates are reasonable. Anyway, training. It’s another thing. Good to have. Good to buy and actually use. Good to purchase training and then actually go through the training.

Not just say, I’ve got the training. Because it does not through osmosis. Like Edgar Cayce, when he would say he could put a book on his stomach and absorb the knowledge. I’m not quite sure that SQL Server training works in the same way. You do have to participate in order for it to be effective. All right. Good thing to do there. If you are so smitten with me that you want to come see me do things live and in person, where you will see me in something probably other than an Adidas shirt, you can catch me in these places on these dates.

Friday, September the 6th, I will be in Dallas, Texas, doing a full day pre-con for Data Saturday Dallas. And then also on the 7th at the regular event. And then November the 4th and the 5th, I will be in Pass Summit for two days of pre-cons with Kendra Little as my charming co-host.

And that’s not co-host in like Johnny Carson, Ed McMahon sort of way. We are on equal footing. This is not like, you know, there’s like the show leader and then like the charming sidekick.

We are equal partners in these pre-cons. So I look forward to seeing you there with maybe some more ChatGPT created images. I don’t know. That seems like fun.

Anyway, let’s talk about these windowing function query plans. So what I want to go through in this one is sort of two things. One, the difference between row mode and batch mode for window function query plans.

And the other thing is difference in query plans when you have and when you do not have a partition by clause. Because that does change things a bit. Also, the type of predicate that you have on your windowing function, whether it’s equality, less than, greater than, can also change the query plan a little.

So, with all that in mind, gosh, let’s get started. All right, let’s move it on this thing. So I’ve got these two queries already run.

And what I want to show you here is without a good supportive index, both of these queries have to do a bit of work to generate the windowing function stuff. The thing is, the row mode query just plain stinks at it. When you have to do this over a lot of data, when you do a windowing function over a lot of data, you just absolutely should not be doing anything in row mode with it.

So, this query takes 9.3 seconds. This query takes 1.4 seconds. Big difference there. And it’s all because of batch mode.

Now, where things that you should know about window function query plans is that in row mode, you will always see these two operators, the segment and the sequence project. Segment is responsible for the partitioning and the ordering.

And then the sequence project is responsible for the numbering. So you put the data in the order that it needs to be in. If you don’t have an index that already has the data sorted the way it needs to be for the windowing function, then you have that sort there, right where my finger ends, right there.

That puts the data in order. Then the segment sort of does the grouping and then the sequence project sort of does the numbering. At least that’s how it was explained to me.

If someone lied to me, I will find them. Remember Boku Delta Miles over here. Diamond medallion darling data. So we have a sort that puts the data in the order that we need it to.

We have this thing that sort of does the grouping, you know, put stuff, you know, maintains the order. And then the sequence project that does the numbering. So, all well and good.

This is what you will generally see in windowing function query plans in row mode. In batch mode, it will look like this. We still have a sort, but notice that sort doesn’t quite, you know, have the problems that the other sort did. And then we will see a window aggregate.

I’ve said this in other videos, but one of the very cool things about window aggregates in SQL Server query plans is they are the only operator currently that is able to read from a batch mode sort on multiple threads. All the rows come out of the clustered index on the comments table, go into the sort on multiple threads.

The sort occurs on multiple threads, but any other operator would have to read from that sort single threaded. So, kind of a cool thing there about window aggregate operators. So, this is kind of the general physical appearance difference of query plans between row mode up top and batch mode at the bottom.

Batch mode gets the window aggregate. And then row mode has the segment and the sequence project. Because we don’t have an index in place, both of these have to sort.

So, let’s move on a little bit and let’s look at what queries look like when we don’t have a partition by clause. Notice that we are just ordering in this one and this one and this one down here. I’m going to run all three of these at once so we can compare and contrast these wacky query plans.

These wacky dacky doos. One of those things is a little slower than the others, wasn’t it? Now, the big difference between partition by windowing functions and ones that don’t have the partition by clause, they only have the order by clause, is that SQL Server eats up the parallel zone a lot earlier on in the plan.

The query plans that we looked at before were parallel the entire way through to the very end where there was a gather streams. In this one, we gather streams really early on. Both of these things gather streams right after the, well, the row mode.

Both of these things, here I go. Being a knucklehead. The row mode plan gather streams immediately after the sort and does the segment and the sequence project in a serial zone.

The batch mode plan keeps the parallelness through right after the window aggregate. And, you know, the batch mode thing is a little bit faster here anyway, but whatever. This one’s a little bit different because, you know, we really just have to, we don’t have to do as much work as we do with the partition by, especially in row mode.

Curiously enough, emitting the partition by in row mode actually gets it pretty close to on par with batch mode. But, you know, most window function queries that you’re going to use, they’re probably going to have to partition by something. So definitely use batch mode on that.

Now, one thing that I wanted to show you that sort of emphasizes the serial zone in the plan is when you use a greater than filter on a windowing function like we’re doing here. This one is uniquely designed to continue to return zero rows. We have a, what we saw in the other plans where we have, sorry, my head’s in the way.

I’m going to like Mario, boop, the clustered index scan. Then we sort, then we gather streams, then we segment, then we sequence project. And then after that, we reopen a parallel zone.

We have a distribute streams operator here that re-puts things out on parallel threads and then re-filters them. You’ll notice that this thing really slows down. This is not a good time.

This greater than predicate, whatever happens in here, it is no good, right? We are not having fun. We do a lot more work in this query. So, you know, be aware of, you know, how you do that.

Of course, if you use batch mode like any sane normal person would, you don’t have those same problems. Again, row mode query plans for windowing functions are nothing but headaches. I, you know, I will use any trick in the book to get batch mode for windowing function queries because in row mode, they just eat it so often that it’s mind-boggling.

I don’t know how we ever got away with windowing function queries without batch mode. It is truly a dismal experience a lot of the time. So, again, this very fast, even with batch mode in place.

And we don’t have the same sort of weirdness with the, you know, the serial, the parallel zone ends and the segment and sequence reject and then the parallel zone reopens. We just have a parallel plan the whole way through, which turns out a lot better for us from a performance perspective. So, in this video, we have gone over some just kind of physical appearance differences between row mode and batch mode window function plans.

Again, in the row mode plans, you will see the segment and the sequence project with an optional sort if you don’t have an index that supports the partition by order by or just order by clause. We looked at queries that only have the order by and saw that they, you know, while they did have all the same operators, the parallel zone and the only order by clause windowing functions ended a lot earlier. And we also saw that SQL Server has to do some where work when you have a greater than predicate in your windowing function filter.

Think of it like this. If you just have a where row number equals one or where row number is like, you know, equals zero or something, it’s real easy for SQL Server to figure out like where that row number would be, right? It’s going to be at the start of every, you know, either partitioned chunk or at the very start of the results for a query or for the row number, right?

Sorry. For a query without partition by only has order by, there’s only one chance for that to be the equality predicate. When you do greater than, SQL Server has to spend a lot more time putting rows through and generating those row numbers to compare them because it has to go like basically to the very end of the result to do it.

So that’s why there’s just a lot more work involved. Anyway. Hope you enjoyed yourselves as usual.

I hope you learned something as usual also. Thank you for watching. And I will see you in the next video where we are going to talk about, if I sneak down a little bit here, we’re going to talk about indexes and index usage and memory usage in windowing function query plans, which is just going to be a thrill ride.

Edgier seat. Hold on. Better hope you have your wood screws in type stuff.

So. All right. I’m going to go. I’m going to go prep for that. We’ll upload this. It’ll be a good time. All right.

Cool. Great. Good job, everyone. We barely stumbled over words we’ve been saying for all of our lives. Phenomenal on that.

All right. Great. Thank you for watching. Thank you.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Troubleshooting Security Cache Growth In SQL Server (USERSTORE_TOKENPERM And TokenAndPermUserStore)

Troubleshooting Security Cache Growth In SQL Server (USERSTORE_TOKENPERM And TokenAndPermUserStore)



Thanks for watching!

Video Summary

In this video, I delve into a peculiar issue that has plagued several client servers—security cache growth leading to various transient problems such as CPU spikes, plan cache issues, and memory-related anomalies. I explain how the security cache, meant to simplify login and permission handling, can balloon out of control if not managed properly. To help you tackle this problem, I share a detailed walkthrough on identifying and troubleshooting security cache issues using specific queries and scripts. Additionally, I discuss trace flags that might offer some relief, but emphasize that they need to be set as startup flags for effective management. For those looking for more proactive solutions, I provide stored procedures and agent jobs that can automatically clear the cache when it exceeds a certain size, ensuring ongoing performance stability.

Full Transcript

Erik Darling here with Darling Data. And I remembered to turn my microphone on, so we’re off to a great start here. In today’s video, we’re going to talk about a very weird problem that I’ve seen crop up on client servers a number of times now and lead to all sorts of weird transient issues. CPU spikes, plan cache stuff, just weird memory things, stack dumps, you name it. I’ve seen this thing be the root cause of all sorts of weird problems. And of course that weird thing is the security cache. It sounds like this nebulous little doohickey that is supposed to make life easier by caching security information about logins and whatnot, but if it grows unchecked, it can cause some real big problems. Before we get into all that, of course, we need to talk a little bit about you and me. And things that I like when people sign up for memberships and contribute just a little bit to making sure that this channel stays free and open source for everyone to use. It’s like four bucks a month at the low end. If you don’t have four bucks a month, I totally understand.

You know, there are things that I’d probably rather spend four bucks a month on too. But if you don’t want to do that, liking, subscribing, commenting, all that good stuff is just another way to make my little heart go all aflutter. Shut up, Intel drivers. If you’re in need of SQL Server consulting, that’s my job. Apparently, I do all this stuff and more and my rates are reasonable. So you can hire me to do what I’m going to show you today for you. It’s fun. It’s really great, fulfilling, really just life-affirming work. If you need training in the SQL Server performance tuning space, you can get about 24 hours of it for about $150 when you use the discount code SPRINGCLEANING. If you look in the video description, there’s a link with SPRINGCLEANING baked right into it and you can use that. It’s amazing technology. The advanced URL technology here at Darling Data.

If you want to see me live and in person, and who wouldn’t? I’m even better in person because you can throw things at me. And, I don’t know, give real likes and comments. You can comment in real life, in real time. I think that’s called a conversation. Weird. Weird. I’ll be in Dallas Friday, September the 6th, doing a full-day training session.

And, November 4th and 5th, I will be at PASS Data Summit in Seattle with Kendra Little doing two days of SQL Server performance pre-cons. So you should come see us at those and you should come see me in Dallas if you happen to be in the neighborhood. So now, let’s get on and talk a little bit about how we can troubleshoot security caches.

Now, my good and dear friend, Josh Darnell, who is an application developer, was able to figure out this part of the demo. I don’t take a lot of credit here aside from doing some nice formatting on it, even though there are a couple things that could use some work, apparently. You know, it’s hard to find good help these days.

And, the whole point of this thing is to inflate our security cache. So, that’s what I’ve done. I have inflated the security cache by using SetAppRoll over and over and over and over again in a loop.

I actually had this loop run. Actually, the first run of it got me to about, like, a gig. So, I ran this a few times to get it up a little bit higher.

Just because it made things a little bit more interesting for me. Not because it’s, you know, really all that fun or interesting or cool for you. But, that’s what I did.

So, what we’ve got here are a couple queries that will help you look at security cache stuff. If you look at this one, you will see that things were cruising along going just fine for a while. And, then at some point, the security cache grew.

So, that’s about 2.3 gigs plus about another gig from the ACR cache store. So, that’ll be about 3.2 gigs total from there. So, this is a tough query to remember.

It’s not very portable. It’s not very interesting. I mean, it’s kind of interesting. Actually, you know, if you look at it and you actually click on the XML column, you can get a lot more information out. I don’t like parsing this stuff out from the XML to show in the tabular result because it makes a lot of, like, duplicate lines that are just kind of messy.

I generally just zoom into where, like, things grew or when things grew or, like, if they, you know, spike up from, like, a lower number to a higher number or a high number to another higher number. And, then I sort of just dig around in here because you can see all sorts of interesting stuff about, you know, entries getting put in but not removed and the size of things. And, it is, you know, mildly interesting if you have this particular fetish.

If you want an easy way, excuse me, an easy way of figuring out if your system cache, if your token and perm user store is growing a lot, you can use my free store procedure SP pressure detector. I’ve got it set up here to only look at memory and to skip some other stuff that’s not really pertinent to us. But, if you run that right at the very top, you will have this section here and you will see user store token perm is about 3.2 gigs total, which I believe is about what we talked about it being from the XML.

When we did the XML query, it was, like, you know, 2.3 plus 0.9 something gigs. So, that’s the size of the token perm store there. Now, you can clear this out manually by running this, DBCC free system cache token and perm user store.

So, but the thing is, if this is something that happens regularly because of your application either using set app role or, like, doing impersonation stuff, like, I think execute as is another thing that can really pump this up. Switching users back and forth in queries for different reasons. I’ve seen a bunch of applications that, you know, log in as one user, switch to another user to do something, switch to another user to do a different thing.

Like, they have different permissions and schemas and stuff. All those things will inflate the security caches. So, you can totally run this to clear that out.

If this is a big long-term problem for you, there are a couple of trace flags that can help. The thing is, they don’t help if you just do this. These have to be startup trace flags for them to really make a difference.

So, if you want to look into what 4610 and 4618 do, if you’re having this problem, go crazy. They’re pretty useful if you’re having the issue, but only as startup trace flags. They don’t fix a problem if you just enable them globally.

If this is a problem that you’re having a lot and the trace flags don’t help and your security cache is still growing, over in my GitHub repo, which I’ll have a link to in the video description, I’ve got a few scripts in there that can help. One of them is a store procedure that will run, look at the size of your security cache, and there’s a parameter that you pass in to say how big of a security cache you care about.

If it grows beyond a certain size, it’ll run that DBCC free system cache call and clear it out for you. I’ve also got an agent job to set that up to run. The schedule, I think, is baked in for like every hour or something.

If that’s not often enough, you can, of course, adjust the schedule. But all of this stuff, you can just hit F5 on. And, of course, if you want to inflate your security cache for some reason, or you just want the standalone analysis scripts here, you can use that.

Also in my GitHub repo is SP Pressure Detector right down here, which you can also get totally for free. You don’t have to like or subscribe or comment on that, but you can get that and also view the biggest memory consumers on your server.

And if that user store token perm stuff is up there, you might want to think about running the DBCC command to clear it out, maybe enabling the trace flags, and maybe using this code to set up a job to clear it out on a regular basis, because you might be having all sorts of weird performance issues and reliability issues because this thing grows out of control.

As for like how big it has to be before I worry about it, generally, once it gets past the 2 gig mark is when I see signs of trouble. If it gets up past like 4, 8, 16, 20 gigs, somewhere in there, then you’re just about guaranteed to have some issues.

So I’m usually pretty aggressive on this, and I usually set that to be around like 1, 1 to 2 gigs to clear out for the store procedure there, because like really anything beyond that, you’re just kind of asking for trouble in the long term.

So I hope that this is not a problem that you have. I hope that you don’t have applications that blow out your server’s security cache, because memory is precious, right?

And if you have, you know, 8, 16, 24 gigs of security cache, that’s memory that your server can’t use for other stuff, like caching data pages or query memory grants or having a plan cache or other things like that.

So it’s a bad problem to have. If you are having that problem, you’ve got some trace flags that you can look into. You’ve got some scripts that you can run to clear it out.

If you, you know, I honestly like, you know, I say try the trace flags, but a lot of people can’t just restart SQL Server with new startup trace flags in place. It might be safer for you to just use the scripts there.

Excuse me. So look at your SQL Server with SP Pressure Detector. If you see high user store token perm or anything like over like the 2 gig or so mark, you might want to think about, you know, clearing that out, see if the problem comes back.

If it keeps coming back, I’ve got you on the scheduled stuff with the store procedure right there. The store procedure also does some logging so you can see like, you know, which runs cleared stuff out, how big the security cache was when the run cleared. So there’s some diagnostic data in there too that’s pretty helpful.

Anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something. I hope that all your dreams come true. I hope that you just get everything you want from life.

It’s a short endeavor and feeling like you are missing out on stuff is never a good feeling. So I hope you’ve got no FOMO. I hope that you get everything that your heart desires, including this video coming to an end.

That’s what I desire right now because I feel like I’m sticking the landing a little bit here. Anyway, thank you for watching. I’m going to upload this and figure out what to do with my life next.

All right. Cool. Thank you.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Catch Me On The Azure DevOps Podcast: Technical Debt

Professional Rambler


I met The Azure DevOps Podcast host Jeff Palermo (X|L) at Red Gate Summit in NYC, where we were on a panel discussing database stuff, ‘natch.

A few days later, he invited me to be on his podcast. Here’s the episode:

If you prefer to listen another way, here’s a link to the episode with a bunch more options.

If you’re an Appler, you can listen here.

Thanks for listening!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Join Me And @Kendra_Little At @PASSDataSummit For 2 Days Of SQL Server Performance Tuning Precons!

Last Year


Kendra and I both taught solo precons, and got to talking about how much easier it is to manage large crowds when you have a little helper with you, and decided to submit two precons this year that we’d co-present.

Amazingly, they both got accepted. Cheers and applause. So this year, we’ll be double-teaming Monday and Tuesday with a couple pretty cool precons.

You can register for PASS Summit here, taking place live and in-person November 4-8 in Seattle.

Here are the details!

Day One: A Practical Guide to Performance Tuning Internals


Whether you’re aiming to be the next great query tuning wizard or you simply need to tackle tough business problems at work, you need to understand what makes a workload run fast– and especially what makes it run slowly.

Erik Darling and Kendra Little will show you the practical way forward, and will introduce you to the internal subsystems of SQL Server with a practical guide to their capabilities, weaknesses, and most importantly what you need to know to troubleshoot them as a developer or DBA.

They’ll teach you how to use your understanding of the database engine, the storage engine, and the query optimizer to analyze problems and identify what is a nothingburger best practice and what changes will pay off with measurable improvements.

With a blend of bad jokes, expertise, and proven strategies, Erik and Kendra will set you up with practical skills and a clear understanding of how to apply these lessons to see immediate improvements in your own environments.

Day Two: Query Quest: Conquer SQL Server Performance Monsters


Picture this: a day crammed with fun, fascinating demonstrations for SQL Server and Azure SQL.

This isn’t your typical training day; this session follows the mantra of “learning by doing,” with a good dose of the unexpected. Think of this as a SQL Server video game, where Erik Darling and Kendra Little guide you through levels of weird query monsters and performance tuning obstacles.

By the time we reach the final boss, you’ll have developed an appetite for exploring the unknown and leveled up your confidence to tackle even the most daunting of database dilemmas.

It’s SQL Server, but not as you know it—more fun, more fascinating, and more scalable than you thought possible.

Going Further


We’re both really excited to deliver these, and have BIG PLANS to have these sessions build on each other so folks who attend both days have a real sense of continuity.

Of course, you’re welcome to pick and choose, but who’d wanna miss out on either of these with accolades like this?

twitter
pretty, pretty, pretty, pretty good

You can register for PASS Summit here, taking place live and in-person November 4-8 in Seattle.

See you there!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

A Little About Loops In Dynamic SQL

A Little About Loops In Dynamic SQL



Thanks for watching!

Video Summary

In this video, I dive into some fascinating techniques using output parameters and dynamic SQL in SQL Server to loop through items like databases or tables. It’s particularly useful when dealing with non-contiguous IDs or missing values, ensuring you can dynamically find the next value without having to manually increment a counter. By leveraging these tricks, you can write more robust scripts that adapt to different database versions and configurations, making your analysis queries more reliable and less prone to errors in front of clients.

Full Transcript

Erik Darling here with Darling Data. And, uh, sorry, I had to delete a video that I didn’t like. Uh, no, no, it wasn’t this video. It was a different, different thing. Don’t worry. This, this one’s going to be great the first time through. Uh, anyway, uh, in today’s video, we’re going to talk a little bit about some cool stuff you can do with output parameters and dynamic SQL that you use to loop through things. Now, a lot of the times when you’re using dynamic SQL, it’s to like, make sure that the right thing happens at the right time based on like contextual stuff. Um, you know, if like, you’re like, I mean, if you’re like me, a lot of people like me, and you write a lot of SQL Server analysis scripts, you might find that different versions and additions of SQL Server might support different views and columns and, you know, bits of information. And you don’t want to hit errors when you run an analysis query because you’re doing it in front of a client. And gosh, that’s embarrassing. Uh, uh, so a lot of the times dynamic SQL is used to sort of detect object existence before like including a view or a table or a column or something, uh, in your query. And also is very, very, very useful for directing queries to the correct database, right? So you say, I want to do this in this database. And then when you get real crazy with dynamic SQL and you have it run across multiple databases, you can, you know, also have that happen. Uh, but you know, sometimes when you write dynamic SQL, it’s because you have to iterate over, like a bunch of stuff like databases and you want to make sure that you do that in the right order. And you want to make sure that the next value that you look for is the right one. Like you, like, it doesn’t always work to say like, you know, uh, like plus one, right? Cause you might have non-sequential IDs or something. Right. And that you would look very silly if you were like, you know, like, Oh, loop one ID one. And then there’s no ID, no more IDs until like 140, or maybe there’s no ID one.

And then you just keep running that loop over like the next incremented number because you just incremented your loop plus one. Cause isn’t that what everyone does in their, in their computer science labs? They, when they, they write their, their while loops and for loops and whatnot, they just say, Oh, plus one. Not the next, not the actual next number, just plus one, throw it on out there. Anyway, before we talk about that, uh, if you, if you like me and you like my free SQL Server content, and you would like to say thank you with money, uh, which I guess would make the SQL Server content, not free. Technically, uh, it would just, it would, it would just be a moderately priced. Thank you.

Uh, I have low cost memberships where you can say thank you to the tune of like four bucks a month. If you don’t have an extra four bucks a month, that’s totally cool. Um, I probably wouldn’t give an extra four bucks a month to some random guy on YouTube either. Uh, depending on how cute he is, who knows? Right. Uh, if you, if you would like to say thank you, in a different way, uh, you can like, you can subscribe, uh, you can, you can leave comments. And while that won’t exactly buy me a bottle of wine, that it’ll give me at least something nice to look at while I drink my wine. So if you have a, an unhealthy, angry, slow, begrudgingly awful performance, SQL Server issue, SQL Server performance issue words in the right order, please. Thank you. Uh, you can hire me to, to consult for you.

Uh, I do all of this stuff and more, and my rates are reasonable. Uh, if you want very low cost training for the rest of your life, uh, you can get all 24 plus hours of my content for, uh, 75% off. That’s about 150 bucks, us, us dollars, uh, after, after, uh, after the discount code kicks in. So, uh, that, that, that, that’s a good handy thing to do. And of course, as always, there is a link that, itself applies that coupon code right in the, in the video description. So, uh, and no, before I forget, this is why I do this stuff. Cause I forget a lot. I even forgot that this slide was next, even though I’ve been staring at this awful chat GPT image for, I don’t know how long, uh, Friday, September 6th, I will be in Dallas for data Saturday. Uh, I will have a full day pre-con about, all about SQL Server performance stuff. And I will also actually be at the actual main event on Saturday as well. Big breath, November 4th and 5th, I will be at past data summit in Seattle with Kendra Little doing two days of SQL Server performance pre-cons, uh, November 4th and 5th.

You should come spend some time with us there. And now, deep breath, let’s get on with the show. So, cause that’s what we do. We get on with shows here at Darling Data. So I’ve got what looks like a pretty standard while loop for SQL Server. Uh, but you’ll notice that there’s one thing that’s missing from this while loop. And that while loop is missing anything that increments I after the thing executes down the bottom there. Pretty wild, right? The way that I do that is with the magic of output parameters in dynamic SQL. Now I know there is almost no business case for this particular thing to be dynamic SQL, except to show you how this works. It’s wonderful. It’s fantastic.

So up way up at the top of, ah, come on, zoom it. Come on, zoom it. Wake up. Uh, at the, at the top of the, the, the, the loop, I have a pretty standard set of things being declared. I have at I, cause everyone names that thing at I, uh, I have at E, which I actually named at E after me. No, it’s, it’s for end, right? That’s the end number. Um, I guess, I don’t know what I is. I guess I should have named I S for start, but, uh, it’s too late now. Um, maybe in the next, maybe in the next world. Uh, and then of course I have an S well, shoot, I already have an S no wonder I didn’t name I S that would have, that would have just been terribly confusing. Um, that was, that’s going to hold our dynamic SQL. And of course our well formatted planned out thoughtful dynamic SQL, uh, is held in S with this. We’re going to select the top one at I, right? So we have at I as a parameter inside the dynamic SQL that gets, uh, that gets declared actually for the dynamic SQL down here. Awesome and amazing. And then we’re also saying where database ID is, is greater than at I. So in this dynamic SQL block, not only are we setting at I up here, but we’re filtering on at I down here. And then when we execute our dynamic SQL in the loop, we’re saying at I is an output parameter and we’re passing in, uh, at I is, uh, I mean, we’re, it has to be shown as an output parameter here so that we get the right value out, but it’s, it’s, it’s both, it’s an output parameter for, for the dynamic SQL and also an input parameter for the dynamic SQL.

And then down here, we’re just going to, you know, have a nice little message print out that says, Hey, this is where we’re at in the loop. Uh, and if you’re, if you’re the type of person who writes dynamic SQL that does any sort of looping or, you know, whatever, um, I would highly suggest using raise error with no weight, uh, over print for like status update stuff in your dynamic SQL, uh, because that tends to work a lot better. Uh, like print on its own has like weird buffer stuff that it has to deal with. And if you don’t fill those buffers up, the print statements can get weight lagged way far behind using raise error with no weight print stuff out just about immediately. If you need to print longer dynamic SQL out, I wouldn’t suggest using raise error because there are more strict limitations on the number of bytes that it can print out at a given time. I think it’s 4,000 or 2,000 something. I, I, 2,048 maybe. I forget. Uh, maybe that’s the max length of the message. Anyway, it’s much shorter than print. Print can do, uh, 8,000, uh, non-unicode bytes or 4,000 unicode bytes. And since dynamic SQL with SP execute, SP execute SQL is always unicode. You have some pretty strict limitations there, but much, much more open than, uh, than with raise error. So, uh, yeah, do that. And then if you have a real long dynamic SQL string, you can like get the length of it and like write a silly, another silly while loop that prints out the chunks of that until you have reached the end of the string. So without further ado, and I, again, I want to make perfectly clear, there is nothing in this that I, I, there is no set at I plus equals one, right? There’s no increment going on here.

So if we run this, I, when it gets passed into here, starts with a value of zero from up here, but then when I gets passed out of the dynamic SQL block, it has the next ID that’s greater than zero. So it actually increments itself by nature of just grabbing the next highest value.

This can be really, really useful when you don’t know what the next highest value is, right? Like, like in our case with, with sys.databases, we are very lucky that we print out one, two, three, four, five, six, seven, eight, right? But if you, if we were dealing with like real user data, where maybe it was one, two, three, 5029, you wouldn’t want to rerun, try to run a loop for all those things that don’t exist. So using the output parameter in this way can help you get to the next value if they’re non-contigious, right? So if even, even if you have an identity column or a sequence object, you may find that you’re, they are not like, like you don’t have an exact, like one, two, three, four, five, six, seven, eight, nine, 10, you can miss, you might have missing numbers in there.

So, you know, fun, fun, fun stuff abounds. The SQL Server. Thanks, SQL Server. You’re, you’re a real, real, real sport. So, well, this doesn’t exactly show off the, the, the amazingness of finding the next value if they’re non-contigious. It does kind of get the point across that this is a good way to do that should you find yourself in that situation. And then again, all you have to do is pass some values out of the dynamic SQL so that you know what the next one to go to is. Anyway, I think that’s pretty neat. I think that’s a kind of a neat trick with dynamic SQL because now you don’t have to sit there worrying about working out what the absolute next value is. You can just go right to it and make your life easier. It’ll make, make everyone happy. You can show this to someone that you’re romantically keen on. I don’t know. Maybe they’ll fall in love with you. Maybe, maybe, maybe this, maybe this is your happy moment in life. I don’t know. You can never predict these things. So anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something and I hope that you will continue to watch this amazing free SQL Server content five days a week or maybe just watch it all one day a week. Because to be honest, I tend to like set aside some time and record a bunch of videos in one day. So that’s why, that’s why like you might see blocks of videos where you’re like, wow, that Erik Darling doesn’t change much. And you’re like, well, that’s, that’s because all these things are about five minutes apart. So tricks of the trade, as they say, tricks of the trade. Anyway, uh, I’m going to upload this. And then when this is done uploading, I’m going to record something else. Amazing how that works, isn’t it? All right, cool. Thank you for watching.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

A Difference Between ISNULL And COALESCE You Might Care About In SQL Server

A Difference Between ISNULL And COALESCE You Might Care About In SQL Server



Thanks for watching!

Video Summary

In this video, I delve into the nuanced differences between `ISNULL` and `COALESCE` in SQL Server queries, specifically focusing on their performance implications and practical usage. Erik Darling from Darling Data provides a detailed analysis of these functions, highlighting that while both can be used interchangeably for most cases, `ISNULL` offers some unique advantages due to how it interacts with non-nullable columns. I also discuss the potential pitfalls of using these functions in join or where clauses, emphasizing their unnecessary use and the resulting suboptimal query plans. Additionally, I share my personal insights on consulting services and training opportunities, offering a discount code for those interested in cost-effective SQL Server education.

Full Transcript

Erik Darling here. That was very unclear. Erik Darling here with Darling Data. Look at all the Darling Data we have. It’s amazing. You’ve never seen so much Darling Data in your life. In today’s video, we’re going to talk about a substantive, substantial difference between isNull and coalesce in your SQL Server queries. Before we get into that, we’re going to talk about a substantial difference between isNull and coalesce in your SQL Server queries. So, just a few things up front about that though. Just a few things up front about my life. If you like this channel, there are low-cost ways to say, thanks for recording videos and publishing videos for free constantly. Which I guess kind of makes them not for free, but otherwise you would have to do other things to say thank you. Like, like, or comment or subscribe. So, you know, there’s that. If you are in need of SQL Server consulting, if you are having health performance emergencies, if you need someone to fix your crap for you, or if you need someone to train your developers so they stop producing crap. I’m pretty good at all of those things. If you need something else, let me know what it is. My rates are reasonable.

If you need some training that doesn’t cost a billion dollars a year, you can get all of mine for life for 75% off with that discount code. And of course, there’s a link with the discount code baked right into it in the description of the video. If you click on that, or maybe copy and paste it, I’m not quite sure what the mechanic is there. You can get everything for about 150 US dollars. So, that’s a pretty good deal. As far as, like, where I’ll be going in my life, well, Friday, September 6th, I have a full day pre-con for Data Saturday Dialist. You can show up there, you can learn about SQL Server, and then you can leave and forget about SQL Server until you need it. But that’s the beauty of it.

And then, November 4th and 5th, I will be at Past Data Summit in Seattle, co-presenting two wonderful days of SQL Server performance pre-cons with Kendra Little. We are going to kick butt. And now, let’s get on with the show here, apparently. That’s what our job is, getting on with shows. All that good stuff. So, when it comes to IsNull and Coalesce, there are, like, functional differences, where, like, Coalesce takes multiple inputs. Great.

But, you know, whenever you read on the internet, like, what’s faster, IsNull or Coalesce? People will do the same stupid performance tests, where, like, they’re just in a select list. And you’re really not going to find much of anything when you just stick IsNull and Coalesce in a select list.

It’s trivial. The real difference for me between IsNull and Coalesce is that IsNull has some superpowers that Coalesce does not. See, Coalesce has an ANSI standard function, and under the covers, it’s a case expression.

And if you dig a little bit deeper, a case expression is just an if statement way down deep. But that’s what it is. It’s not special.

Well, Microsoft is want to do. Didn’t really, like, improve upon Coalesce or even attempt to. They just made it write a case statement out behind the scenes, and that’s all you’ve got. So, one thing that IsNull can do that I think is a superpower is when you have a column that is actually not nullable, you do not allow nulls in that column, SQL Server can skip the IsNull.

And say, well, whatever, it’s not null anyway. It can’t do that with Coalesce. Coalesce still builds out the case expression in either case.

So, I did the needful, and I ran these two queries before I started recording, because you can’t see it, but if we go to the armpit zone, that’s probably a bad name for it. I should call it the rib meat zone, maybe. The Cote de Boeuf.

If, then, you’ll see that there’s about a minute and nine seconds of execution time under there, and, I mean, well, I am fully capable of blathering on for a minute and nine seconds. I didn’t feel like it. I just wanted to cut to the chase a little bit.

So, let’s look at these two query plans. Ah! Stop doing that. You murdered me. Now, we have an index on the votes table on creation date comma vote type ID. So, creation date is the leading column in the index.

This is, of course, the bigger deal for Sorgability stuff, like when the leading column of the index is the thing that you put the function on. Residual predicates, it’s like, well, no, whatever anyway. Like, it’s going to be probably a residual predicate almost no matter what you do.

So, whatever. I mean, SQL Server can do multi-seeks, but if you look in my video history, you’ll find some videos about multi-seek query plans where things don’t go well. They evaluate a lot of data depending on how they’re written.

So, looking at these two things, rather, let’s go back to these query plans here. For the first query, which is pretty fast, right? It’s about two seconds.

We seek into that index, right? Even though we have that creation date column wrapped in is null, since creation date is not a nullable column, SQL Server throws it out and we still seek right into the index, which is a pretty good plan, right? Look at that.

There is no mention of is null in this predicate whatsoever. Nothing. Nothing at all. It’s wonderful, right? It’s great. There’s no is null.

It’s just a scalar operator. Wonderful. Good for us, right? We figured it out. We cracked the case. If we go look at the index scan down here, you will see a case expression. All right?

You see that? All this case expression in here. Oh, you know what? Of course, I covered up the… There’s the case and there’s the end. And… Coalesce doesn’t shortcut or short circuit the way is null does.

And that leads us to get a really terrible query plan. In this case, the terrible query plan that we’re concerned about is a top above a scan. I can’t begin to tell you how many times I’ve seen this particular pattern in a query plan.

And the query is awful. A top above a scan is almost never a good sign. And if you run the query and get the actual execution plan, you can almost guarantee that this will be the absolute slowest part of the query.

So, what did we learn today? Coalesce? Just a case expression.

No superpowers. Is null. If you, you know, for some reason… And, you know, you see this with developers a bit where they don’t actually know their data. They don’t love their data.

They don’t spend any quality time getting to fall in love with their data. They just, you know, do random things. Write random queries. Copy stuff from other places and paste it in. Ask chat GPT to write a query for them.

And a lot of the times the result is going to be the same. There’s going to be just unnecessary is nulling of things. I see it quite a bit.

And it’s depressing every single time. So, if you’re trying to choose between which function to use, assuming that there is no functional requirement for you to use Coalesce, I generally do prefer to use is null because SQL Server can do some stuff with it that it can’t do with Coalesce.

If we’re talking about preferences generally, you shouldn’t have is null or Coalesce in a join or where clause because you’re asking for trouble. But, at least with is null, Microsoft can at least bail you out of a little bit of that trouble when the query runs because it will look at the column and say, hey, that column can’t be null anyway.

We don’t need to mess around here. So, there we go. I hope you enjoyed yourselves.

I hope you learned something. I hope that you will continue to not put is null and Coalesce in your join and where clauses. And, well, I suppose that’s probably the bigger lecture point is don’t use either one.

But, if you’re going to be that dumb, be a little bit less dumb and probably just use is null. Yeah. So, there we go.

We got a little bit less dumb today. That’s the goal, right? A little bit less dumb every day. Less dumber by the day. That’s us. All right.

Cool. I’m going to record some other stuff now. You might see some file names up at the top that might indicate what we’re going to be getting after over some of the next few videos.

And, well, it’s going to be a grand old time. So, anyway, once again, thank you for watching. Thank you.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

In Memory Table Variables In SQL Server: Still Pretty Stupid

In Memory Table Variables In SQL Server: Still Pretty Stupid



Thanks for watching!

Video Summary

In this video, I delve into the often-overlooked world of in-memory table variables, particularly focusing on their behavior within SQL Server. Starting with a lighthearted introduction to my database named “Trash,” where I’ve set up memory-optimized data and created a simple procedure to demonstrate the quirks of these variables, I aim to highlight both their limitations and potential pitfalls. Through detailed query plans and cardinality estimations under different compatibility levels, I explore how SQL Server handles these table variables, revealing that even with full knowledge of the row count, it often fails to optimize queries effectively. By comparing behaviors across compat levels 140 and 150, I underscore the importance of understanding the implications of these changes for your database performance.

Full Transcript

Erik Darling here with Darling Data, and uh, doing my best to look like a real serious, real serious, take me seriously consultant. I’m gonna stand, look tough, right? I’m gonna butch things up a little bit. I’m not really sure what else I could do aside from get some face tattoos, but I don’t know. I think, I don’t think my mother would like that very much, so we’ll, we’ll probably skip on upsetting Mrs. Darling at this, at this point in her life. We’ll, we’ll wait, we’ll wait until it’s safe. Then, then we’ll get face tattoos. Alright. In this video, we’re gonna talk about how stupid in-memory table variables are. Uh, every once in a while, you know, some, some, some, some Microsoft added in-memory stuff to SQL Server in 2014, and every once in a while, they’ll write some, like, some, like, just lethargic driftwood blog post. Like, please use these, please use this feature. Someone, someone, please use this thing. Uh, there, there, there are, like, two good use cases for in-memory anything in SQL Server. Uh, I’ve yet to find a really good use case for in-memory table variables. Uh, in-memory regular table, tables, not table variables, regular in-memory tables can be pretty good shock absorber tables. You might find online gambling companies use them to some great effect. You might find, uh, online ordering companies use them to some great effect during, like, very busy times, like, you know, holidays, you know, special events, things like that. Um, where you have a small amount of in-memory data that stays hot for a short amount of time, which can then be transferred out to a disk-based table, uh, where once it’s, like, past the point where all the locking and latching stuff that, that goes on, uh, once that stops, right? Like, once, once the, once the hotness is over, once, like, you know, all the bets have been placed, you don’t need to avoid all the locking and latching anymore, because from then it’s just people figuring out if they want or not. It’s just a bunch of selects. It’s, uh, mostly the, the, the locking stuff and the latching stuff that people, people will care about for that.

In-memory table variables, I just never found a reason to care about them. Mostly because, uh, they’re not that different from regular table variables in a lot of important ways. So that’s what we’re going to look at today. So, before, before we get into that stuff, uh, if you, if you like the channel and you don’t want to start seeing, like, Geico commercials or something before, in the middle of, after every video, uh, you can, you can sign up for a, a, a membership here. They’re, they’re, they’re cheap. It’s, like, four bucks a month or something.

If you can’t do that, which I understand, not everyone can. Not, not, not everyone has an extra four bucks in their pocket at the end of the month. Uh, there was a time in my life when I, I, I usually didn’t have an extra four bucks in my pocket ever. Um, it was, it was all dedicated to a bar tab. Uh, you, you can do other things to, to let me know you care. Uh, you can like videos, you can comment on videos, and you can subscribe to the channel and join nearly 4,200 other data darlings out there in the, in the, in the, in the world who get notified when, when I publish these videos.

Uh, if you are in need of, uh, SQL Server Consulting of the performance, health, tuning, emergency, training variety, well, I got you covered on all that. If you need something else, let me know. My rates are reasonable. Uh, if you need low cost training, I got that too. You can get, well, 24 hours of performance, tuning content at the beginner, intermediate, and advanced levels.

I guess that says expert, huh? Expert levels, uh, for about 150 bucks US when you apply these, the discount code spring cleaning. Um, when I set that code up, uh, I, I, I had just switched to a new video platform. Um, and, uh, it was springtime for Eric and, uh, I used that code cause it seemed funny and it’s just kind of stuck since then.

So, even though it’s at least currently August 15th or so, middle, mid August, uh, it’s, it’s always springtime at the darling data sale. So, um, it’s springtime for you as well. Now, uh, I, I will also be speaking in person at a couple events in the near future.

Friday, September 6th, I will be at Data Saturday Dallas. The full day pre-con on the 6th and at the Saturday event on the 7th where I will be, uh, delivering a couple regular sessions. And then November 4th and 5th, I have two full day pre-cons at PASS Summit in Seattle, uh, where me and Kendra Little will be teaching you really all that you need to know about SQL Server performance tuning over, over the course of a couple days.

So, if you want to, if you want to get a whole lot of performance tuning knowledge, a nice condensed block of time, there are a couple great ways to do it. I can also teach you how to make great images that make a lot of sense with AI. ChatGPT never lets you down.

Um, you know, ChatGPT is a funny thing because, uh, a lot, a lot of people are really pushing AI hard, Microsoft included. You know, the whole, the whole co-pilot thing. And, um, you know, I think one thing that’s really a good exercise for anybody, especially executives, who are like, AI is going to change the world, um, spend some time with it.

Ask it questions about something you know really well. Uh, ask it to do something you know a really great way how to do. And, and see, see if AI gives you an answer that, that is correct.

Or, uh, gives you a process that, that is, that is correct. Because I think you’ll be really surprised to find most of the time it doesn’t do the, most of the time you ask the, you know, any, any AI LLM tool to do something.

Or you ask it about something where you have a significant amount of experience, knowledge, and you can, you can, you have a good BS detector about this stuff. The answers you get back would terrify you.

I know they terrify me. Uh, one thing that gives me hope about AI is that whenever I ask it to write a query, it does all the same dumb stuff that regular developers do.

So I feel like me as a performance tuning consultant, I love AI. Because I’m going to be fixing the same 12 problems over and over and over again. Because no one knows any better.

Not even AI. AI messes everything up. All the same stuff that like a junior developer would mess up, AI messes up. It’s wonderful for me.

The future is so, I mean, I don’t know if the future is so bright, but these recording lights are very bright. I’m not going to start wearing sunglasses on video like some kind of antisocial, but man, I’m excited.

I’m excited to see what happens. So anyway, let’s look at how stupid in-memory table variables are. All right.

So, on to SQL Server Management Studio, where you’ll see that I have created a database called Trash. And I’ve created a database special for this because Microsoft, in its infinite wisdom, despite having 10 full years to work on this SQL Server feature, have not given us a way to turn off in-memory anything once we enable it for a database.

You can’t turn it off. It’s on forever. It’s there forever and ever.

You’re stuck with it. It is like a herpy. It does not leave your body. It’s just always there. It’s like a Lego piece that you stuck up your nose when you were seven.

Things never coming out. You’re just going to have to live with it. I think I have a Lego piece on this side. At least it feels that way most days.

So, I’ve created a database called Trash for this specific exercise because I want a database that I can drop and not think about ever again. Right?

And I’ve told SQL Server that this database contains memory-optimized data. And I have created a file group for this memory-optimized data that should give you a really good sense of exactly how I feel about in-memory table variables.

So, after I did that, and there was really not a whole lot of reason to revisit a lot of this stuff, what I did was create just a very abridged version of the post table in the Trash database with just a couple columns in it.

I don’t want to recreate the whole thing. I don’t need the whole table to show you how silly this is. And then I inserted all the data that I have from the Stack Overflow 2013 post table for those two columns.

And I updated statistics with a full scan. The reason why I wanted to do this is because I want to show you that SQL Server gets cardinality right at first. And then as soon as it’s in that table variable, it gets kind of forgetful.

Right? So, after that, I created a type, a table type, that is memory-optimized with an index on the two columns in the table. So, apparently memory-optimized things don’t like clustered indexes.

That’s fine. Not everyone likes clustered indexes. A lot of people who have paid me a lot of money to tell them they need clustered indexes didn’t like clustered indexes at first either.

So, like, I totally get it. You’re in the same camp, right? Just dumb people, right? And now I have a procedure called table variable test. And this table variable test takes a single integer called ID.

And inside of the store procedure, we declare a table variable as the post thing table type that I created up there.

And we also create just a simple local variable in here that I’m going to use to swallow results, right? Because this thing doesn’t need to return results.

I just need to show you the query plan stuff from it. And so, what I do is I insert into my memory-optimized table type variable here for any records that match the ID column.

And then I get a simple sum from the table type variable where the ID equals the ID that I pass in. And then I get a full sum from everything in there, right?

So, absolutely everything in there gets summed up, right? So, the first thing I’m going to do is I’m going to show you what happens under compat level 140.

And this is important because Microsoft changed some stuff about table variables in compat level 150 assuming that you have paid Microsoft money, Microsoft enough money to like you, which is by using Enterprise Edition.

So, when we run this and we look at what happens in the query, starting the query plans, we already know what happens in the query. Insert some data in the sum sum data.

Sum sum data. SQL Server knows exactly how many rows are going into the table variable here. Here.

2,000… 27,901 rows. Enter our table variable. Over here, right? Now, one table variable limitation that I end up talking to a lot of people about is that when you modify data in a table variable, you cannot use a parallel execution plan.

Granted, for this particular insert, a parallel execution plan would probably not bias anything. It’s already short and small and fast and we don’t really need to worry too much about it.

But I’ve run into a lot of situations where people would willy-nilly choose table variables or temp tables, just flip a coin, use whatever, I don’t know, you know, kind of two-face it.

And they would be very surprised when queries that they had that ran very fast to like, you know, say the select portion of an insert slowed down a lot when they started inserting data into a table variable.

They couldn’t quite figure out why. And usually it’s because the insert query that does a whole lot of work to get the rows together that you need to insert can’t go parallel anymore.

If you see this big, oh, actually my finger disappears a little, pretty early on, trying to point up that way. But if you look at the long word up there over my head that is in desperate need of some spaces, you will see a non-parallel plan reason that table variable transactions do not support parallel nested transactions.

Huh. Kind of missing something at the end there. So anyway, in-memory table variables have the exact same limitation in that regard as regular table variables.

Bummer. Okay. Well, do they have any good sides? Not that I can figure out. So under compat level 140, both of these queries, despite SQL Server having full knowledge of the 27,901 rows entering the table variable here, make no attempt at doing any better here.

When we ask it how many rows will qualify for the owner user ID that we just used up here, SQL Server still says one. When we ask it about the whole entire table, SQL Server still says one.

Thanks, SQL Server. Great, great use of, great use of resources there. Great use of all the smart people, all the mathematicians, all the PhD students, all the everyones who have ever worked on SQL Server.

One. One. That’s it. Under compat level 150. Wow, compat level 250? What version of SQL Server will that be?

If things follow along, let’s see, vNext would be 170, because that would be the next highest one. So that would be 180, 190, 200, then 1, 2, 3, 4, 5.

So that would be eight versions from now. So we would probably be somewhere around SQL Server 2045 or 2050 if we had compat level 250.

Unless Microsoft does a 1, 2, skip a few, because, for whatever reason, I don’t know, maybe counting by tens would get boring. Maybe, maybe, I don’t know, whoever is in charge of SQL Server will get bit by something and end up with 20 fingers, and they’ll start counting compat levels by 20.

I don’t know. I can’t possibly, I can’t possibly guess why that might happen. So, under compat level, starting with compat level 150, again, assuming that you have paid Microsoft’s friendship tax, so they pretend to like you, like that Patrick Dempsey movie where he, that girl spills red wine on her suede, mother’s suede outfit, and he pays to get it dry cleaned, so she pretends to be his girlfriend for the summer.

If you’ve paid Microsoft’s Can’t Buy Me Love tax, that’s the name of the movie, if you’ve paid Microsoft that tax, they will do something a little bit better for you, starting with compat level 150.

Let’s just make sure that ran. Where, it’s not that, SQL Server will allow a parallel execution plan to a table variable.

No, we still don’t support table variable transactions and not support parallel nested transactions. It’s not that. Does this get much better?

Wow. 27,901 of an estimated 167. Again, even though we are reusing this here and we are reusing this here.

Uh, 167. Thank you. Thank you.

Thank you. Thank you. Where things do get somewhat better is here. where now we get without a where clause we get full table cardinality.

So we say SQL Server says, oh, well, 27,901 rows went into that table. I guess 27,901 rows are going to come out.

The funny thing is that now table variables are sort of like parameters where you can get table variable sniffing.

So if we do this, right, and we look at what happens, well, now we reuse this plan, right, because this is totally what happened before in SQL Server with parameters sniffing.

But the first time we ran this, 27,901 rows came out. This time we only got nine rows. So SQL Server used the cardinality estimate from before for this plan. Well, the thing is that now it uses it again for this plan, right?

So now we get nine out of the 167 that it guessed before. And now we get nine of the 27,901 that it guessed before.

So even the small favor that Microsoft did for us starting with Compat Level 150 in SQL Server 2019, again, assuming that you’ve paid Microsoft the Can’t Buy Me Love tax, we’ll just call it the Patrick Dempsey tax for short.

Now, instead of just worrying about parameter sniffing, now you have to worry about table variable sniffing. So ain’t life grand?

Ain’t life just grand? So things haven’t really gotten the lot in life for table variables has not really improved all that drastically.

Now, that’s about all I have to say here. I need to go drop this database immediately because I’m starting to feel dirty. I don’t want this cold sore on my server anymore.

We’re going to take some Valtrex and rub some Abriva on this thing. Get it in there good. Fix it all up. Hopefully never to return again.

Is there a herpes vaccine? I don’t know. I’m not a doctor. I’m not qualified to say if there is or if there isn’t. Anyway, I hope you enjoyed yourselves.

I hope you learned something. I hope you will not fall for terrible blog posts promoting the use of memory-optimized table variables because gosh, they are useless and gosh, you don’t want to turn on this feature for your database that you can’t turn off again and I still don’t understand that.

I still don’t understand that feature, that decision, whoever’s decision that was. Man, I hope they work for Boeing now.

About it there. What did I say? I hope you enjoyed yourselves. I hope you learned something. I hope that you will like and subscribe and comment and buy training and hire me to do consulting and all that other good stuff.

And I’m going to go, I don’t know, this is, I think, this is the last one I’m going to record today because honestly, this one has gotten me down a little bit. So I need to go pep myself up.

I’m going to, I don’t know, I’m not sure what I’m going to do yet. Something that makes me feel better. Anyway, thank you for watching.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Signs You Need Dynamic SQL In Your SQL Server Queries

Signs You Need Dynamic SQL In Your SQL Server Queries



Thanks for watching!

Video Summary

In this video, I dive into some key signs that indicate your SQL queries might benefit from using dynamic SQL. Starting off big and moving to the specifics, I cover scenarios like when you frequently use local variables in your WHERE clauses or have conditional logic based on parameters. These situations often lead to suboptimal query plans due to how SQL Server handles cardinality estimates for local variables and if-logic during compilation. To illustrate these points, I walk through a few examples and show how adding the RECOMPILE hint can sometimes solve performance issues temporarily, but ultimately, dynamic SQL is the more reliable solution for long-term optimization. Additionally, I share some upcoming events where you can catch me in person, including Data Saturday Dallas and Pass Data Summit, as well as discuss other ways to support my channel through memberships or by simply liking, commenting, and subscribing—because every bit of engagement helps keep the content flowing!

Full Transcript

Erik Darling here with Darling Data, doing my Darling Data damnedest to keep you educated and entertained about SQL Server. Alright, that was pretty good. Nailed that. I think that’s a one taker. I should just cut the video off now. It’s not going to get better than that. In today’s video, we’re going to talk about some signs that you need Dynamic SQL. Now, there are of course signs beyond this, beyond the ones that I’m going to show you. that may become apparent in what you need to do with the query. Like, if you need to pass in like a schema, table, database, server name, something like that, for multiple different database. Let’s start, let’s start, let’s go big to small server, database, schema, table names. That’s a good use of Dynamic SQL. What we’re going to focus on in this video are some signs that for query performance, you are likely to need Dynamic SQL. Before we get into that, just a few casual reminders for the viewers out there at home. All of this content is free. You can freely watch it. If you feel strongly about supporting my channel, I have very, very low cost memberships for like four bucks a month. Eventually, I’m going to expand the offering and make it a little bit more enticing. But for now, getting a YouTube video like five days, five days out of the out of every week seems pretty good. I don’t know. We’ll see. We’ll see what comes up in the future. If you are unable to participate in a monetary exchange for whatever reason, maybe maybe you drank it all. I don’t know. I don’t know what goes on in your life.

I don’t know. Maybe you just bought a cool new car or something. Maybe the price of gas is killing you. I don’t know. But I promise you I will never cost $4 a gallon. If you’re unable to participate for whatever reason, other ways to make me feel all warm and fuzzy and fluffy inside are to like, comment and subscribe. Wonderful things that you can do for free. Make me feel good. If you are in need of SQL Server Consulting, these are things that I help people with on a daily basis. I can do other stuff too. But this is what I like the best. If you need something else, I don’t know. My rates are reasonable. We can discuss whatever you need.

If you are in need of SQL Server training, perhaps, because you just don’t get enough from these videos. I have dedicated focused performance tuning training that goes from beginner to intermediate to advanced. With the discount code spring cleaning, you can get the whole caboodle, the shebang, the enchilada. I don’t know. You can get the meat lovers for about $150. So that’s a pretty good way to spend $150 if you get $150 burning a hole in your pocket.

I will be live and in person at a couple events coming up. Friday, September 6th, I will be at Data Saturday Dallas doing a full-day pre-con. November 4th and 5th, I will be at Pass Data Summit doing double-team pre-cons with Kendra Little. So if you’re going to be in Dallas or you’re going to be in Seattle and you would like to see me, these are times you can do it.

If you’re not, I forgive you. We can still be friends, maybe. Now, let’s talk about these dynamic SQL worm signs. Now, these are all things that I end up using dynamic SQL to fix for performance problems with, client queries with, also demo queries, in case you haven’t noticed.

In case this is the first video you’ve seen on this channel, I do this in like a billion other videos. We’ll go through these things because they’re important. So one of the first signs that you probably need dynamic SQL is if you use a lot of local variables in your code and you end up using those local variables in where clauses.

I suppose you could also use them in join clauses. I don’t often see them there, but they would have a profound effect there as well. Local variables do not get treated the same as parameters or literal values.

SQL Server does not use the smart part of the histogram to give you cardinality estimates for local variables. It uses some dumb fuzzy math to figure that out. So one very good sign that you need to, if you have a query that’s slow and you’re using a local variable, the first thing to do to figure out if you’re having a problem there is put a recompile hint on it.

If it’s still slow, if you still get crappy plans from it, you have another problem. If the recompile hint fixes it, then you should invest in some dynamic SQL to get better cardinality estimates to have a properly performing query. Another very, very big sign that you might need dynamic SQL or that you probably need dynamic SQL or you need to hire me as a consultant to figure it out is if you have if logic that executes important queries based on the outcome of some parameter value.

Unfortunately, for you, not for me, for you, when SQL Server compiles query plans for some batch, whether that batch is some queries like this or in a store procedure, it compiles execution plans for all the queries, regardless of whether they will actually execute for that compilation or not. So you get cardinality estimation for that compilation, which might not make a whole lot of sense if you follow the if branch up there the first time and the if branch down there the second time.

Because the if branch down there is probably not going to get anything very good. Right. So this is another great sign that you might need dynamic SQL because if you change these raw SQL queries to dynamic SQL, they will only compile plans when they execute, not when they don’t execute.

So you can get much, much, much, much more reliable query performance if you use dynamic SQL here instead of just running whatever select. Another great sign that you need dynamic SQL is if you do stuff like this. Now, again, like I said in that first example, one way to test if this is your problem and whether dynamic SQL is going to be a good option for any of these things is to try them with the recompile hint.

The recompile hint fixes them. You can, of course, just use the recompile hint. I don’t care.

It might just be the easiest thing for you to do at the time. Stick option recompile at the end of the query. The problem solved. I don’t know. Maybe just call it there. You could do that. But not everyone can just recompile every query all the time.

Eventually, you hit some limit with that where you might be unhappy with the way SQL Server is spending its CPU time. So, again, if you test any of this stuff with a recompile hint and find a positive effect and you rewrite it as dynamic SQL, you get much better sort of long-term benefit from that. So, again, this is another good sign that you might need.

Oh, why did you do that to me? That you might need dynamic SQL is if you have this sort of conditional where clause logic in your queries where you’re saying, oh, is score greater than this parameter or is this parameter known? What can we ascertain from this?

Great use of dynamic SQL is to just build the where clause you want. Great use of dynamic SQL is to just execute the query you need when you need it. All right?

Good stuff there. Another one that I see quite often when I’m working with clients is some conditional join logic. So, you might see a bunch of joins out to a bunch of tables, but not every join will always be used. I cover this in a video about startup expression predicates where we resolve the majority of our issues with, again, say it with me.

Dynamic SQL. It’s great. Wonderful for this stuff because then you just join to the tables you need when you need them.

And you don’t have to deal with weird cardinality estimation issues if these are sometimes one and sometimes zero. And you reuse execution plans. And sometimes they’re good.

And sometimes they’re bad. That’s not exactly parameter sniffing. It’s, oh, you just being a jerk. Another thing, another sign that you might need dynamic SQL would look something like this.

It’s conditional existence check. If you’ve noticed a theme here, a lot of the times when you need dynamic SQL is when you are asking the optimizer to come up with a good execution plan based on some conditional logic at compile time. And this will bite you in the behind just about every single time.

This sort of decision making stuff does not make for a happy optimizer. I’m going to repeat something that I’ve said in a lot of videos. Again, if this is the first video that you’ve ever seen from me, this might blow your mind.

Anything that makes your job easier makes SQL Server’s job harder. So doing cute little things like this and some of the other conditional stuff and the local variable thing, you know, it’s a really nice shortcut for writing a query. But it’s just not going to perform well over time.

The bigger your data gets, the worse these problems get. The more of this stuff you have to clean up, the harder your job is. Because eventually you have to make SQL Server’s job easier so that your job will be easier. Otherwise, you’re just going to spend the rest of your life firefighting performance issues.

Well, maybe not the rest of your life. Depending on your employment contract or other local factors, you might get fired or go get a new job before you actually have to fix all this stuff. You might see things starting to get difficult and say, I’m out of here.

I need to go screw something else up from the ground floor, right? It might happen for you. But this is another case where, you know, you would want to write dynamic SQL to just tack this where exist clause on if check post is something that you want to do for the query.

If check post is not something you want to do for the query, you don’t need to put this anywhere near your query. It’s ridiculous. Who would do such a thing?

Now, we’ve talked about some of the most common signs that I see in client queries where dynamic SQL is a great way to fix a performance problem. Again, if you apply an option recompile hint to a query suffering from any sort of conditional logic or from any sort of local variable weirdness and your query suddenly speeds up, it’s probably a pretty good sign that you need to buckle down and rewrite some of that beautiful SSMS red text that builds strings dynamically and executes them based on precisely what the requirements of the query are and not just a, well, any old thing.

We don’t really know. We’ve got to be flexible. We’ve got to make sure everyone can do everything all at once.

Well, that’s not really good for your query plans and that’s not really good for your SQL Server performance. If you’re doing any of this stuff currently in your queries, test with the option recompile hint. If that helps, rewrite that as nice parameterized dynamic SQL.

If you don’t know how to do that, you can hire me to do it. I love dynamic SQL. It’s one of my favorite things in the world. Someday I will have a yacht named dynamic SQL.

It would be cool if I could get a private jet named dynamic SQL, but I sort of realized the limitations there. Maybe I’ll have a private jet named entity framework. That seems more feasible to me.

So I’ll have a yacht named dynamic SQL and a private jet named entity framework. And I still won’t be able to retire. Someone’s got to keep putting gas on those things, right?

Anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something. I hope that you too will learn to acknowledge the greatness, the grandiosity, the grandeur of dynamic SQL when it’s properly applied, constructed, and used in SQL Server. I’ve had great luck with using it over the course of my career.

One thing that people always ask about is, well, if I use dynamic SQL, will SQL Server reuse the query plans? Yes, when it should. Using sp-execute SQL for dynamic SQL gets you just about equivalent plan reuse as if you write a store procedure.

Store procedures, reuse execution plans. So does dynamic SQL when used with sp-execute SQL. If you just use exec some SQL thing, maybe, probably not.

But the other one, but sp-execute SQL, mwah! K-bet. Lots of plan reuse there. Because sp-execute SQL is a store procedure.

It’s executing a query, parameters. All right. Cool.

I’m exhausted. Okay. But I’m having a good time. So I just keep going. I just keep trucking. All right.

I think that’s enough for this one. I’m going to go think about what I want to record next. It might be something about is null and coalesce, and it might be something about in-memory table variables, and how they’re not that great either.

So who knows what’s going to happen? It’s going to be wild. It’s going to be crazy. Hopefully, hopefully no one spills lube on the floor again. Anyway, thank you for watching.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Demo Materials For Data Saturday Dallas #DataSaturdayDallas

If You Missed the Links


Here are the demo downloads for my two sessions at Data Saturday Dallas.

And of course, the demo database lives here.

Thanks for attending!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

Join Me And @Kendra_Little At @PASSDataSummit For 2 Days Of SQL Server Performance Tuning Precons!

Last Year


Kendra and I both taught solo precons, and got to talking about how much easier it is to manage large crowds when you have a little helper with you, and decided to submit two precons this year that we’d co-present.

Amazingly, they both got accepted. Cheers and applause. So this year, we’ll be double-teaming Monday and Tuesday with a couple pretty cool precons.

You can register for PASS Summit here, taking place live and in-person November 4-8 in Seattle.

Here are the details!

Day One: A Practical Guide to Performance Tuning Internals


Whether you’re aiming to be the next great query tuning wizard or you simply need to tackle tough business problems at work, you need to understand what makes a workload run fast– and especially what makes it run slowly.

Erik Darling and Kendra Little will show you the practical way forward, and will introduce you to the internal subsystems of SQL Server with a practical guide to their capabilities, weaknesses, and most importantly what you need to know to troubleshoot them as a developer or DBA.

They’ll teach you how to use your understanding of the database engine, the storage engine, and the query optimizer to analyze problems and identify what is a nothingburger best practice and what changes will pay off with measurable improvements.

With a blend of bad jokes, expertise, and proven strategies, Erik and Kendra will set you up with practical skills and a clear understanding of how to apply these lessons to see immediate improvements in your own environments.

Day Two: Query Quest: Conquer SQL Server Performance Monsters


Picture this: a day crammed with fun, fascinating demonstrations for SQL Server and Azure SQL.

This isn’t your typical training day; this session follows the mantra of “learning by doing,” with a good dose of the unexpected. Think of this as a SQL Server video game, where Erik Darling and Kendra Little guide you through levels of weird query monsters and performance tuning obstacles.

By the time we reach the final boss, you’ll have developed an appetite for exploring the unknown and leveled up your confidence to tackle even the most daunting of database dilemmas.

It’s SQL Server, but not as you know it—more fun, more fascinating, and more scalable than you thought possible.

Going Further


We’re both really excited to deliver these, and have BIG PLANS to have these sessions build on each other so folks who attend both days have a real sense of continuity.

Of course, you’re welcome to pick and choose, but who’d wanna miss out on either of these with accolades like this?

twitter
pretty, pretty, pretty, pretty good

You can register for PASS Summit here, taking place live and in-person November 4-8 in Seattle.

See you there!

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. I’m also available for consulting if you just don’t have time for that, and need to solve database performance problems quickly. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.