ICYMI
Last week’s thrilling, stunning, flawless episode of whatever-you-wanna-call-it.
Video Summary
In this video, I dive into the world of SQL Server query plans and execution, addressing some common questions and misconceptions head-on. Starting off with a bit of frustration towards YouTube’s tendency to mess up my recordings, I share how important it is to understand the nuances between estimated and actual plans. I explain that while there’s technically only one plan, the pre-execution show plan (the estimated plan) and the post-execution plan (which includes actual metrics) are distinct entities with their own unique characteristics. This discussion leads into a detailed exploration of how many indexes might be too many, covering factors like locking, blocking, memory usage, and workload patterns. I also touch on the complexities introduced by features such as Read Committed Snapshot Isolation (RCSI), offering practical advice for those considering its implementation in their databases. Overall, this video aims to provide a clearer understanding of SQL Server’s query optimization process and the considerations involved in database design and tuning.
Full Transcript
All right. Try that again. The do-over of all do-overs. The grand do-over. I like when audio works. Audio should be better now. Should be. YouTube does awful things to me. Every time, every time I do this, every time. I hate you, YouTube. I hate you, YouTube. You’re the worst. The pits. Gigantic, awful. I wish this was something stronger. Canada Dry Sparkling Seltzer Water.
All right. Who has questions? There are like a billion people here. Someone has to have a question about SQL Server. Someone. Someone out there.
Must have a question about SQL Server. Otherwise, why would you show up? What, what good reason is there to show up and watch me do nothing? Play with scissors? You just start cutting my hair randomly.
You don’t want to do that. No one likes that. See the dancing. It’s always moving. Just do what I want. When you dance, Kenneth. You see anyone saying, hey, Kenneth, good job dancing.
Kenneth, dance for me. No. Did I see the discussion yesterday about actual first estimated plants? Yes, I did. And it is the same thing that I’ve been saying since the dawn of time.
That when you talk about an actual plan, it’s just the plan that has the actual metrics in it. There’s no. Well, I won’t say there’s no functional difference.
But that’s, that’s where things get tricky. That’s where things get a little bit awkward when you say that there’s, there’s no difference. Because when you get an estimated plan, there are things that don’t happen. That happen in the actual plan.
Or what we should start calling them are the pre-execution query plan and the post-execution show plan. There are all sorts of post-optimization rewrites that may end up in the query plan. All sorts of things that happen post-optimization.
If you look at an extended events. If you ever look at extended events there, when you look under, oh gosh, what’s it called? So actually this brings up an interesting thing. So I’m going to get to everyone’s questions, but I want to share this because it’s funny.
If you use SSMS 18 and you have it crash because you use extended events or like you open up the extended events thing. If you do new session wizard instead of new session, it doesn’t crash, which is amazing to me. Anyway, I’m going to just do a couple of things here because I want to talk about how many different events there are for show plan.
There are four. Actually, let me make sure that I have the debug thing opened up too. Okay, there’s four altogether.
There’s post-compilation show plan. There’s post-execution show plan. There’s pre-execution show plan. In query store generate show plan failure. Let’s leave the query store one out of this. There are three show plan events. And extended events that you can use to capture execution plans.
The pre-execution show plan is, you know, exactly what it sounds like. The query hasn’t been executed yet, but it has a query plan. The post-compilation show plan is after SQL Server says, okay, I got a query here. I’m going to, this is, I’m going to plan.
And then you have the post-execution plan, which may contain rewrites that weren’t, stuff like bitmaps and other things that weren’t available or that weren’t explored yet when you had the pre-execution show plan or just the post-compilation show plan. The post-execution show plan is also going to have the actual stuff in it. So there’s all sorts of, I mean, while there is functionally one plan, you might see different things in the post-execution show plan than just the actual metrics.
You know, like, like query plans now get all sorts of extra stuff in them, right? They got wait stats, they get operator times, they get all sorts of cool stuff. And you can only see that in the actual, in the actual plan.
Let’s call it the post-execution plan. So you can only see it in the post-execution plan. But there are also optimizer rewrites that might show up in the post-execution show plan that would not be in the pre-execution plan. There are decisions that SQL Server makes that might show up in there that wouldn’t be in the pre-execution plan.
So I think for the for the sake of all of sanity, there, the way that we should really refer to query plans are the pre-execution show plan, right, which is like estimated pen like control L or whatever button you hit up in management studio and then the post-execution plan, which contains actual metrics about things. So there is one query plan, but there are two versions of the plan. There is the pre-execution show plan, the post-execution show plan.
And I’m right about that. You can tell everyone on Twitter Erik Darling’s right about that. Don’t listen to anyone else. Anyway, we have other questions now. Now that I’ve been talking for how long is it that 20, 30 minutes, half hour, 45 minutes.
How long did I talk about? That was a long talk. That was a long, long talk. I just never talked about anything that long. Sammy says, how many indexes is too many? I don’t know. I don’t know. You tell me. How many indexes do you have?
And are you having problems with those indexes? Too many? Okay. So let’s see. What things that you look at when you want to find, do I have too many indexes? What happened in my life that I have so many indexes? What went on that caused so many indexes to show up and what am I seeing now? Great questions.
So if you have too many indexes, you will see more locking because you have more objects to lock. You will see more blocking because more things are getting locked. Unless you have magical settings turned on or you use no lock everywhere. But then writers will still block each other.
So you might see more of that. You might see worse use of memory. You might see, you know, that metric that everyone poops their pants about. You might see PLE get really low because all of a sudden you need to read a whole bunch more stuff into memory.
When you modify it, you might see more, more indexes need to end up. Come on into memory. We’ve got to change you. You got pages. You got to write on those pages. Let’s get into memory. You might see PLE drop. Oh boy. You might see increased page IO latch SH if you’re needing to go out to disk to get more indexes.
So it’s like saying, it’s like asking someone, well, how many calories is eating at maintenance for you? That’s going to depend on a heck of a lot of stuff, right? Like when you talk about eating at maintenance, right? You talk about like calories in versus calories out. So clearly I specialize in calories in, but if you talk about eating at maintenance, like how many calories, how many indexes that can I have?
How many calories can I have? Well, it depends. How sedentary are you? How much time do you spend sitting on your butt? How much time do you spend up being active? How many times, how much time do you spend doing stuff at the gym, going for walks, swimming, riding a bike, thinking real hard, cleaning?
Oh man, it was funny when I first met my wife, she was like, you know, if you clean the house, you burn like 200 calories. Yeah. Okay. Your cardio is made. I will just make messes for the rest of your life. You will be skinny.
But yeah, it’s like, like what is like, so how do you eat at maintenance? Well, you have to figure out how active you are, how inactive you are. If you have a table with a very, very low write profile, right? A table just doesn’t take that many writes for some reason.
Like, you know, you load data in like once a night or something, and then you read data out, it’s going to matter, right? Like, write patterns matter for how many indexes you can have. That and like settings like RCSI, which we have a question about, I promise you I will get to.
You know, if you’re using no lock-ins, you can have way more indexes because you don’t have to worry about locking. But you know, you know, there are other factors involved. How much memory do you have?
Oh, there’s lots of stuff, right? There’s lots of stuff to think about. There’s no such thing as like, how many indexes is too many for everyone or anyone? Like how many calories can I eat? Because you have to adjust that based on what you do, right? It’s not just make a Blakins statement about that. I hate people who make, I hate everyone who makes blanket statements.
You can quote me on that. I hate everyone who makes blanket statements. Beat that. But yeah, so you know, it really depends on your, you know, starting from the outside and working in. If you have an availability group or if you have, you know, mirroring because you’re still cool or if you have log shipping, you know, then that’ll affect how may affect how many indexes you have because you have to start sending those indexes to other places.
If you have a crappy San, I don’t just mean disks. I mean the whole storage area network, you might be able to have fewer indexes because you might be spending a lot of time going out to disk and to read those indexes in. You might cause a lot of contention on those shared resources that, that exist between your server and the disks and the, and the storage area network.
If you have a lot of memory that might not matter. If you have way more memory than data, which is, which I’m sure is all of you. You’re all, you all have a terabyte of memory and like a hundred gigs of data.
You know, it’s, that’s going to change things, right? You can have more indexes because you don’t have to worry about that stuff. If you have a high right workload, you can have fewer indexes. I don’t know. There’s a lot of stuff, a lot of stuff. How many indexes is too many depends on you and your hardware and your choice of H a technology, H a D R technology.
Lots of things go into that equation. Yeah. Figure it out though. Look at your weight stats. Look at your locking, look at your blocking, look at your workload. Look at, uh, you know, your servers error logs.
See if you have a lot of see if the server is, you know, going going crazy with like 15 second IO warnings or flush cash or like saturation messages. That’s what I would do. Anyway. Kenneth says I found a property that tells you if the plan came from the cash or not.
Yeah, that’s a little wonky though. I wouldn’t always rely on that. I’ve seen cases where like I’m using a recompile hint and it’s telling me that the plan came from the cash. So I would be careful with that one. Uh, Kapil says I’ve been in this heated debate with developers to enable RCS in this database where there are about a thousand of blocking and deadlock throughout the day. We are on default and I am proposing to enable RCS and test it out from temp TB.
I am good. What are the things that should be taken care of? And what are the caveats will enable enabling RCS? Well, uh, excuse me, the revenge of the seltzer. Um, so here’s, here’s the thing. I generally love RCS.
I think it’s wonderful, but. And here’s here. There are a few butts with it. Well, not big butts, medium sized butts like 90s, like 90s butts, not 80s butts. So the thing with RCS, I of course, is, you know, you say you’re good from temp TB.
So I’m going to assume that you have multiple temp TB files. If you’re on a version prior to 2016, you probably have trace flags one, one, one, seven and one, one, one, eight enabled. If you’re on a newer version, 2016 and up, those are the default behavior. So you don’t have to worry about it anymore.
Uh, so. What I would start being concerned about, um, a, if you have any queries that depend on locking and blocking for correctness, like if you do any queuing, like if you say I need to, you know, um. What’s the, what’s the classic analogy?
I need to assign tickets to whoever. Uh, doesn’t have a ticket available. RCS. I can mess with that because you might be reading version of rows where someone, you know, uh, already has a ticket, but the, that hasn’t like fully gone through yet or something. And you might like double ticket someone. So RCS can affect query correctness where you depend on blocking.
The other thing that you have to start worrying about is long running transactions. So the version store cleans up in different ways, depending on if you have RCS or snapshot enabled. So long running transactions affect how much version store you’re taking out in different ways.
But you need to start being more wary of long running transactions. You also need to start being more concerned about, um, well, gosh, how many indexes you have, because the more indexes you, you need to, uh, modify the more stuff will end up in the version store. You also need to worry about the size of your transactions again, going back to what we were talking about for indexes.
If you have, if you are loading or modifying lots and lots of rows, your version store is going to get lots and lots and lots of big. So you need to be a little bit careful there and you need to, uh, start batching your modifications in smart ways. Like say only update, like, you know, a hundred thousand rows at a time.
So you don’t blow out your version store and therefore tempt. So there’s lots of stuff. Lots of stuff. Um, but there, you know, as far as like the initial set of things, I would, you know, a pay attention to queries that use cues, right? Let’s say like, I need to do things in a certain order and I need locking to do that.
So the other thing is that our CSI isn’t going to necessarily help with deadlocks because deadlocks are primarily, um, primarily. I’m going to say primarily because it’s not a hundred percent. Again, I hate people.
I hate everyone who makes blanket statements, but deadlocks are primarily, uh, writer on writer contention and our CSI is not going to help that. It will significantly help readers and writers get along better. Snapshot isolation you can use to, um, help writers not conflict, but that gets tough. That gets difficult because then you have to start handling exceptions where, uh, like a transaction tries to run and update a role that’s not there anymore.
So, bye. So you need to start handling that. Um, let’s see. Let’s scan down the list here. V says back in the day when you were learning to tune queries, did you ever hit major roadblocks in terms of progress? I’m interested to know what if so?
Yeah. You know, um, of course. Yeah. You always, there’s always going to be something, right? Whether it’s like, you know, you are in a position where, you know, you really want to change an index, but you can’t change the index. You’re the one adding index.
You can’t add an index. You really want to do something and you, for some reason, can’t do it, right? Like, I hit that all the time when I work with people who are like, we have entity framework and I’m like, great. And so, development time must be really fast. Great.
Because you can’t really do a lot with those queries. And any framework calls off and writes whatever query it wants. So, you know, it’s nice that now you can inject query hints, which is wonderful. But, you know, with EF, it’s a lot of like, you know, trying to like force plans, either plan guides or query store if someone has that turned on. That’s always a tough one.
You know, and then stuff where, you know, you see a bunch of anti patterns, right? And you’re like, well, these are like, you know, I’m going to like step through my playbook of stuff I know can help queries. The first thing I’m going to do is I’m going to ditch these anti patterns and I’m going to make things better by reversing those.
And then, holy crap, like you make things worse. Like there have been times I’m like tuning query. I’m like, ah, local variables, scale our functions. Now you’re doing all this stuff wrong.
This is all messed up. And I’ll like, I’ll like start plucking these things out one by one. I’m like, why is the query taking longer? Why is this so much lower? What was happening before? Like, what, like, how did I make things worse by taking out the things that everyone says are bad? And, you know, it’s because again, people make these blanket statements and they’re not going to be wrong.
They’re often bizarre. Bizarre. So, you know, and it’s always frustrating too when, you know, you, you invest a lot of time learning about something and learning the best ways to go about trying to tune things. And you start making these changes that, you know, have helped like lots of queries in the past that you’ve used and the steadfast, loyal query tuning tricks that like worked and done stuff.
And then you like, you start to like, this does nothing is helping. Nothing is changing this query. And that’s when, you know, you do have to, you know, sort of start, you do have to reexamine your, your, your playbook at that point and say, okay, what am I doing wrong?
What can I do differently here? And, you know, that’s also when the investigation kind of has to go beyond, okay, I’m changing things about the query and I’m changing things about the indexes, but I am not getting the expected results. And that’s when you kind of have to go a level deeper and you have to start figuring out, okay, well, you know, I’ve got, I’ve got these changes that I’m making that should be making things better.
What’s wrong now? And you kind of have to start like, okay, well, like, you know, if I’m running this query, what else is going on in the server? Like, what is the serve?
What’s what feedback is a server giving me about what’s happening here? Like, am I, am I, you know, changing things, but am I using more CPU or less CPU or doing more writes or more reads or less reads? Am I being blocked? Is like, there’s just some fundamental issue with the server where it’s like, just like a, like a thing that I’m never going to be able to vault over. Right.
Like, you know, I think I blogged recently about when I was working with a client and, you know, like I would, like I’m, I’m, I’m up early. I’m always up or I’m, I’m, I essentially never sleep. I’m like four hours a night, something like that. But, you know, I’m up, I’m up early. I’m like, you know, like I like to get in and do stuff.
I like to, you know, go to the gym later. I look to do all my work early so I can get out and, you know, like I’m tuning this query and like, I’m making okay progress, but like it’s like six in the morning. I’m like, yeah, I’m like, got this thing down from like, I don’t know, 10 seconds to two seconds or something. And then like, is the morning war on?
I was like, I’m like, I want to show this to people. And I’m like, like seven o’clock. It took seven seconds again. And then like eight, nine o’clock. It was like 20 seconds, 10 or 11 o’clock. It was like 30 seconds. Like. How did this get slower?
And like I wasn’t being blocked by anything because I was in my own separate database. But this server was just so hammered with other queries. I was hitting like thread pool. I was hitting like resource semaphore weights. I was, I was getting knocked around by other act. There was just like things about the server that meant this query was never going to be reliably fast.
I could get it to be faster. And I said a vacuum like when there was nothing else on the server. And maybe if every other, like if every other query running on the server got tuned, this thing would be reliably fast. Or like if every other instance of this query were tuned the way I had it tuned, like they would all like take up fewer resources.
So I wouldn’t be as blocked out as I was. But the end of the day was like baffling. And, you know, sometimes, sometimes you hit roadblocks that aren’t your fault. So there’s lots of stuff in there. So, yeah, I don’t know.
There’s that. Let’s see. Sammy says great analog. Thank you. I try. I try my best to be an eight track man. Let’s see. Lee says personally, I would watch out for the version store size and having our CSI turned on.
Yes. Good job, Lee. I think I think that’s a new picture. I like it. Nice sky behind you. Sam says if they’re literally duplicate indexes, is there any overhead dropping a non clustered if it’s a primary key? I don’t understand that question.
If it’s an exact. So generally, when you have a primary key, it’s also the clustered index. And if you have a nonclustered index on top of just that primary key column, it can be helpful because then you can use that that narrow index to look up the same values that you would in the primary key and SQL Server knowing that is the primary key knows that it’s unique. So it can do all sorts of fun stuff there.
Of course, you know, there’s going to be overhead, but most of the overhead I find in indexes is not with the insert pattern. Most rows get inserted like OLTP wise, like like one row at a time or maybe like five or 10 rows at a time if you’re updating like an orders table with like the items in the order or something. But so like most insert patterns are like, you know, customer comes in and does something like you might like audit it or, you know, they might my new customer, right?
You typically had one new cut, you know, like 10 new customers that get loaded or like a million new customers to get loaded in at once unless you do something weird in the application. But anyway, you know, you know, it can sometimes having a narrower do like slightly duplicative index is a good thing because, you know, if your primary key is a clustered index, you can get pretty bogged down. If you’re just constantly leaning on the clustered index for things.
So, you know, well, it can be helpful and totally be helpful. I think the classic example is, you know, looking at like, say, like only have like a clustered index on a table and say, like select count from table, right? And look at how many like set statistics time and IO on.
Look at how many reads you do. Look at how much CPU you use. Then create a nonclustered index on the clustered index key column or columns or whatever, and then do the same count. So it was ever can use a smaller index, right? So like the smaller indexes are like, even if they’re duplicative of the bigger indexes, I’m more concerned with a bunch of nonclustered indexes that are duplicative of each other than I am a nonclustered index. That’s slightly do that slightly duplicative of the clustered index just because I don’t like leaning on clustered indexes for stuff.
They’re big, right? They’re like the table. They’re like, you know, big strings in there or XML or JSON or bar by big strings. You have to read all that stuff, you know, potentially.
SQL Server is pretty good about not reading lob data when it doesn’t have to. But if you have like regular string data in there that’s like not max or 4,000, 8,000, not on overflow pages, then yeah, you know, it’s like I’m totally cool with having narrower versions of indexes for SQL Server to use and not and have like a smaller memory footprint, hopefully. And, you know, be able to read faster and all that other good stuff, right?
Like density is important to you know how many how many rows you can fit on pages is also pretty important. So I like to, you know, I like to have my indexes be as dense as possible. I can I can read it.
I can read them quickly. Let’s see. But Bill says exactly. I have those with separate 10 DB drives on SSDs. Kerberos. What about I don’t do that stuff. Don’t ask me about Kerberos. Let’s see.
Cabell says I have max four to five. I’m gonna assume indexes per table. This DB is 10 terabytes with partitioning enabled. Oh, okay. All right. 10 terabytes is like, you know, pretty big. I hope you’re not storing a bunch of like PDFs and stuff in there. That’s always a favorite of mine.
Like we’re like, we have a 40 terabyte database. It’s huge. You can’t do anything with it. And I’m like, well, what’s in there? And they’re like PDFs images. I’m like, well, there you go. Good news. I have excellent consulting advice for you. I have unbeatable consulting advice about that.
Don’t do it. Done. Unbeatable. Don’t do that. Don’t do it. Don’t stop. But we need to edit PDS and SQL. I’m like, no, you goddamn.
People have people want to do funny things. And like you and like when, when you’re first learning about C, you’re like, oh, that’s a neat trick. I remember, you know, like when I, whenever I, it seemed like when I was first learning stuff, whenever I like asked the internet a question about SQL Server, I would end up on SQL Server Central. And you would find people write these articles like generating barcodes and like QR codes and like, and like ran and like whatever random numbers, editing PDFs and HTML.
And you’re like, wow, you spent a lot of time doing that. And then like, you know, I just, I just, the more you learn about SQL, you realize like you spent a lot of time on that bad idea. Like, wow, you, you really invested a lot of time in that bad idea.
That’s, that’s, that’s kind of sad. Someone write articles. It’s like, no, no, please don’t do that though. It’s nice that you figured out how, but please don’t.
Like what’s that? It’s that, that Jurassic Park thing spent so much time asking if you could, you didn’t bother if you asking if you should. Don’t come on. Let’s see.
Lee says, I would agree. We still have deadlocks when we have RCSI in all our instances. Yeah. It’s just one of those things you got to, I mean, if you have, I mean, if you truly have a lot of indefeatable deadlocks, your absolute best bet in the world is retry logic.
It like it, I would, I won’t say it’s hacky to do it in stored procedures. Like it’s not hacky. It’s just maybe not my favorite pattern.
I would much rather do it in the application and just like, like retry something a few times, like wait, like a hundred milliseconds and retry. Like, because then at least you can send something back to, you know, whoever is trying to do something. Like you can say, like, you know, like you can either say like update a screen that’s like, has like a progress bar on it or say retrying transaction or something like that.
So that, you know, they have some feedback. It’s not just like, wait, like let’s, let’s see deadlock monitors every five seconds. So let’s say it wakes up and it takes a couple of seconds to do something.
So let’s say waiting seven seconds and then just getting a, like a red blob. You’re like, wait a minute. What happened? And then like, you know, trying, I’m going to do something again. So I like app retry logic a lot. Deadlocks have a very specific error number.
So it’s pretty easy to capture. You can do it in store procedures too. And I’m fine with it. There is totally okay with me there. It’s I just like applic. I just like when I just making developers do stuff. I like making developers do work more than I like making SQL Server do work. Like go program something.
What do we pay you for? Let’s see. Bill says just customer data. And yeah, we’re designed for some of the tables, especially those data types. It’s just 24 seven and data keeps coming. Yeah, I hear that.
Um, uh, let’s see, let’s see what other, what do I have anything charming to say about that? Um, I think, you know, so if you can’t sell them on RCSI, if they’re like, we don’t want every single transaction using this, then there’s always snapshot isolation. So you can, you can sell them piecemeal on things, right?
So the nice thing about snapshot isolation is that you get all the benefits of RCSI, but you have to ask for it, right? So you have to say, please, SQL Server, may I have the snapshot isolation in SQL services? Yeah, no problem, pal.
I got you. So, you know, if you have like, if you have read queries that you know are long running, you can say, okay, from you know what, we’re going to turn on snapshot isolation. And we’re just going to try it with these queries first, we’re going to see how it goes, right? We’re, we’re just going to try it as toes in the water, flick it a little bit, see what’s going on in there, make sure there are no snakes or worms with teeth or evil fish or snapping turtles.
Amoeba, brain eating amoeba, make sure that we have nothing too crazy in there. And then, and then, you know, if, if you can sell them on, on the, like, like, say you have reporting queries or just like queries that do a lot of reads or for some reason, and those keep getting blocked. And snapshot isolation is a good way to introduce people to the wonders of optimistic isolation levels, because you can sell them on the big queries and then you can, you can say, okay, look, our CSI, I know it swings a big bat, right?
Just, that’s just right over the head. But, but, but snapshot isolation, you can, you can get in there and like really, like a, like a watchmaker, figure out which queries you want to apply it to, just use it for those. So I would, so maybe if you can’t sell them on our CSI, you can sell them on snapshot isolation.
You can save them on like the, the, the bit by bit thing. That would be, that would be my goal. I think that’s what I would go with. He says worms with teeth is code for no lock, right? You know, no lock just gets this bad rap.
I can’t figure it out. Just kidding. I would literally say no lock is just misunderstood, but man, it’s, I don’t know. The worst part about like anything to do with no lock is.
There’s no like just dead simple alternative to it. Because SQL Server by default is pessimistic. If SQL Server were optimistic by default, which it should be, which it is an Azure SQL DB.
And gosh, darn it. You wouldn’t have people making this mistake. And it sucks to have to like lecture grown grown ass people. You shouldn’t use no lock.
Here’s why. You shouldn’t do it. They’re like, but it made my life better. You’re like, yes, but you might have wrong data. And they’re like, where? I don’t know. How do you know?
That’s, that’s like, well, you could have incorrect data. You could have incorrect data. You could see incorrect data. It’s not a good idea. No lock doesn’t mean you’re not taking any locks. No lock means you’re not respecting other people’s locks. And so, you know, it’s misnamed is the first problem.
It’s misnamed. It should be with no care. Like, I don’t care what I get. Give me something.
I don’t care. With no care would be a much better name for no lock. Anyway, I’ve been going for over a half hour now. I’m going to hop on. Well, I have about 20 minutes to eat before I have another call. So I was on a call all morning and a call right before this, and I’m going to be on another call with the same headphones on.
My ears are going to start smelling like headphones. It’s going to be disgusting. Anyway, I’ll see you next week with my headphone ears. Anyway, thanks for coming. I hope you had fun and learn stuff, and I will see you next time. Goodbye.
Adios. Yeah. Bye.
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.