Dynamic SQL vs OR Clauses in SQL Server
Chapters
- 00:00:00 – Introduction
- 00:02:15 – Dynamic SQL for Query Tuning
- 00:05:34 – Case Expressions and Join Clauses
- 00:08:45 – Performance Comparison
- 00:11:06 – Index Intersection Benefits
Full Transcript
Erik Darling here, Darling Data, and today’s video, we’re going to talk about a little technique that I sort of, I don’t know, I don’t want to say invented, because saying you invented something is, well, it’s a bit much, right? It’s quite presumptive. But it’s just something that I sort of started, I did, and I want to share with you. And it’s about using dynamic SQL to sort of trim down or clause queries. Like, you know, you get those queries that are like, where something blah, blah, or blah, blah, blah, blah, blah. Anyway, so like this, this is sort of another take on like the unpredictable search thing, but it’s not like the kitchen sink catch all one. So stick with me. Because if you’re expecting that you’re wrong. And I’m going to show you in a minute. Before we do that, down in the video description, if you would like me to invent query tuning techniques on your servers, you can hire me for consulting. Isn’t it your lucky day? You can also buy my training if you would like to learn how to do these things on your servers. Wouldn’t that be great? The Learn T-SQL with Erik course down in the video description below. Wonderful, wonderful repository of information and knowledge that I have put together that the robots have not quite stolen yet. They’re still pretty dumb about a lot of this stuff. If you want to become a supporting member of the channel, you can also do that. You can buy me one half of some kind of coffee drink.
A month, four bucks. Not too bad. You can also ask me office hours questions that remains free. For some reason, I don’t know, I feel like maybe I ought to start charging a nickel on that. Make sure they put down a deposit. I don’t know. Anyway, if you if you are, I don’t know, either really smart, or really broke, or you don’t feel like talking to me or something like that. You can always just like subscribe and tell a friend because maybe maybe a friend of yours will feel differently and perhaps want to interact or engage with me in some form of wacky hijinks or misadventure. You can get my free open source SQL Server performance monitoring tool from GitHub. There’s a link here. There’s that link is also cleverly woven into the video description. Totally free, totally open source, no email, no phone home. It’s better than all the third party tools out there that charge you an arm and a leg and a foot and an eyeball and maybe a couple unmentionable parts. And, you know, it’s, it’s all me, you know, kind of just the stuff that I care about monitoring performance wise and SQL Server, putting it out there for everyone to use a, you know, beautiful charts and graphs. And if you are a robot friendly person, it has built in optional opt in MCP servers that you can flip on.
And have your own personal robot companion, look at your performance data and just your performance data. And maybe help you figure out some of the problems you’re having. Coming up. Well, I mean, that is this week, isn’t it? I will be at Pass on Tour Chicago. We’re going to set a little bit of a theme going here, where I’ll be teaching an advanced T-SQL pre-con. That’s May 7th and 8th. After that, I will be dragging my behind to Poland to this wonderful SQL Day conference. May 11th through 13th, where, lo and behold, I will also be doing an advanced T-SQL pre-con. After that, I will be recovering from what will most likely be a very heavy drinking, what do you call it, trip to Poland. Because I think that’s what you do there, as is customary. And then I will be going to Data Saturday, Croatia, June 12th and 13th, where, shockingly, I have an advanced T-SQL pre-con. After that, maybe, just maybe, I will have an advanced T-SQL pre-con at Pass Data Community Summit in Seattle, Washington, November 9th through 11th. We’ll just have to see. All right. With that out of the way, May continues. The weather in New York has barely improved. Today was actually quite a nice one, but that is a rarity in my neck of the woods lately. Mostly it is just too cold and very windy, and I think we should bomb Canada. Anyway, let’s go to SQL Server Management Studio. And what I want to start showing you here is the sort of beginning pattern of the query that I ended up tuning. I’ve sort of fitted things to the Stack Overflow database as best I could. It’s not quite as great a demo as the one that I actually tuned was, but I think you’ll get the point, and you’ll appreciate it. So, you know, there was sort of like a static part of the WHERE clause, you know, filtering on some stuff. And then there were a bunch of sort of case expressions in the WHERE clause. And it was like, well, if the minimum score equal, where the score is greater than, well, if the minimum score is zero, then we just say p.score, which, you know, since it’s greater than or equal to, it always finds itself. Otherwise, we will go to the min post score in, you know, some table thing up here. I think in the original one, there was not, it was just, it was like, there was like two tables. There wasn’t a temp table involved. I had to cheat a little bit because I couldn’t quite get it right otherwise. But it was sort of like, every time this ran, it kind of did the same thing. Now, I’ve created for this, you know, a bunch of single key column indexes, because that was, you know, part of what was going on in the, the, the real situation. And then one wider index that encompasses all of the columns that we would be or causing on down here. So if you run this for a bunch of different permutations of searching different things, so like putting different numbers into all this stuff, you kind of get the same execution plan over and over again, like performance on this one isn’t terrible. But I do want to show you that you can make a difference, even in queries that already look like they are pretty fast. But in real life, you might find this query pattern and be like, oh, this is dreadfully slow. Why? Why would anyone do this to a server? So every single one of these has basically the same plan, right? It doesn’t matter if you search for almost nothing, or you search for everything, this all does roughly the same thing, right? You know, you grab the data that’s in the temp table, you nested loops joined to the post table, and you spend two 300 milliseconds in here, seeking on various things, depending on what you might find. And but like one of the real annoying things is that like a lot of those predicates, especially from the case expression end up at the join condition, right? So like, you’re not fully filtering out all of the rows that you could, when you’re touching the base table. And that’s, I find that personally offensive. Right. And so that’s what all those query plans look like. Your first instinct might be to rewrite the query to something like this, and say, well, you know, I think that like, or rather, I know, because I watch Erik Darling’s YouTube channel about SQL Server performance tuning, you’re a smart cookie, you might say, I get a bad feeling about case expressions and join clauses and where clauses, and I feel like I should take that case expression out, and perhaps write the query in a way that is maybe SQL Server will smile upon, right? So you might take out the case expressions and rewrite them as sort of or expressions, right? So you might say, and the min score is zero, or the score column in the post table is greater than or equal to the min post score that is in some other table, right? In this case, it’s a temp table, it doesn’t have to be an attempt table. But this all ends up in roughly the same condition, right? In the, you know, you join off to the post table, you are able to seek into an index here for like the at least the begin and end dates. But, you know, you still got in the nested loops, all this stuff, right? It’s all the or you can see the ors, and the and all that stuff sprinkled in throughout. So, you know, that doesn’t quite get us where we need to go. So what I what I what I did, and what you could do to if you felt felt so inclined, is to write some dynamic SQL, to figure out what data actually exists in, you know, your starting place, and figure out if based on that, you need to tack on any of those where clause elements to expand that and ors.
right? Because you could take out the and or sort of like, is it this or is it that? I don’t know what’s going on, you can take some of that element of surprise to SQL Server out, and you can get better queries and plans, right? So what we’re going to do here is say, well, like, we don’t really need to search on this, if you know, we don’t have, if we don’t have a minimum post score that’s greater than zero, there’s no point in asking if the score column is greater than equal to itself, right? And, you know, same thing with the view count column, the same thing with the profile, the min answer count column, and same thing with the min comment count column, right? So if we run all those, we get a much tidier execution plan, right? Because we don’t even need to bring in bring that temp table in. And we can just seek to if we’re just certain if like, we don’t have any of the other data available in there, we can just search on the creation date column. But as we get other other columns involved, we can we can start filtering out the data from the base object as we’re touching it, rather than like get only filtering out some of it, bringing a bunch of stuff into the join and having to do all that filtering there. What I think is particularly interesting about this scenario is if we come up to the indexes, and we drop the wide index, right, so that this this index here called everyone, we drop that because that was across all of the columns, and we rerun these, like, like the plan itself, like it changes a lot.
a little bit for these, right? And just instead of using that one wide index, we hit the clustered index, scan that this is about twice as slow. You know, again, it’s the same problem where like a bunch of stuff gets evaluated at the join, rather than when we touch the table. At this point, we’re consistently just apply those creation date predicates there. And it’s the same deal with the or clauses, right? If we come over here, and we rerun all of these with that dropped, these all get the same query plan too, right? So they’re all doing just about the same thing. I’m not going to belabor that point too. hard. But what I think is neat is if you use the dynamic SQL version of this, SQL Server can actually do like some index intersection stuff, right? Like for this one, well, all we do is seek into that creation date index. And as long as the demo gods are smiling upon me, this will all work. And this one, we use two of our nonclustered indexes, right? We seek into the one one index on creation date. And then we seek into another index on score, right? Because we can we can do that SQL Server is a smart cookie, it can it can it can use multiple nonclustered indexes to apply multiple seek predicates. And sometimes that’s a good thing, right? Sometimes that cost based optimization works out. And if we look at this, where we applied three predicates, now we have creation date score. And I believe that’s comment count, if I’m, if I’m remembering correctly. And for the final plan, we touch all four nonclustered indexes and seek into all of those. Actually, I think that’s five now, right? Yeah, one, two, one, I can count one, two, three, four, five. Yeah, there we go. So we do all this. And I think this is kind of a neat thing, too. We’re like, as as you start writing queries that give SQL Server less to guess about, you can have some very interesting effects, not only on query performance, but on the query plan to where SQL Server can do a little bit more of a little smarter cost based optimization stuff. I’m not saying that this is always the plan you want. I’m just saying it’s an it’s another sort of interesting artifact of writing smarter, cleaner, queries. Anyway, I hope you enjoyed yourselves. I hope you learned something. Both of those things, right? And I will see you over in tomorrow’s video where I think we will we will talk a little bit more about indexed views. Because we started talking about those, I don’t know, 3000 years ago. And then I think I have some more to say on them. So we will do that. 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.