All About SQL Server Stored Procedures: Table Variables for Logging

ll About SQL Server Stored Procedures: Table Variables for Logging


Video Summary

In this video, I delve into the nuances of using table variables in SQL Server stored procedures, particularly focusing on their role in logging errors and handling rollbacks. I explore how table variables can be useful for tracking progress within transactions, especially when you need to maintain a record even if an error occurs or the transaction is rolled back. However, I also highlight that while they are handy for certain scenarios, table variables might not always be the best choice for logging data, especially in complex operations involving large datasets. The video includes practical examples and discussions on when it’s appropriate to use table variables versus other methods, ensuring you make informed decisions about their implementation.

Full Transcript

Erik Darling here with Darling Data. And in today’s exciting, outstanding, completely AI-free video, we’re going to talk about store procedures, still. Carry on talking about SQL Server store procedures. But we’re going to talk specifically about using table variables in the context of logging things about your store procedure in the face of errors and rollbacks. Because for some reason that I cannot explain, every time you are talking about the performance differences between temp tables and table variables, and you’re like saying, hey, if we change this table variable to a temp table, we can make this procedure go faster, someone will decide to chime in with the time in with the time in with the time in with, but table variables, they survive errors and rollbacks. And you’re like, so what? Except with more words, so instead of a long so, inject some colorful language into the so what? Because completely irrelevant to the topic at hand. We’re talking about, when we’re talking about performance, we care about performance, we don’t care about errors and rollbacks. It’s like we’re looking at a reporting store procedure that doesn’t even do any, there’s not a transaction in here. There’s not an error, there’s not a rollback, there’s not a commit. There’s nothing. Why? Why do you bring this up? Why? Why did it, why do you decide to inject the conversation with this meaningless knowledge? You just, you just need to act like you learned something at some point? I don’t understand your point of view on this. Anyway, before we do that, let’s talk about you and me and the birds and the bees. So if you like this channel content just enough to spend four bucks a month, on it, you can use the link in the video description to join the channel as a member. If you do not, if you have not quite reached, not quite reached consensus or formed an opinion on the channel, you can do other stuff. In the meantime, you can like, you can comment, you can subscribe. And if you feel so inclined, you can even ask me questions at this link, which is also done in the video description, that I will answer on my office hours episodes.

When I answer five of your questions at a time and we have fun. If you need help with SQL Server, this is an unruly beast that needs taming that needs performancing. You can, of course, pay me money to take care of them. Health checks, performance analysis, hands on query index server tuning, you name it, responding to performance emergencies and training your developers so that you do not run into as many performance emergencies. is all the name of my game and as always, my rates are reasonable. Promise. Take a look around. If you would like to get some training from me in lieu of perhaps other things, if you would like some real high value content, you can get all 24 hours of my training for 75% off.

That is around 150 US dollars and that comes to you for the rest of your life. Link to do all that stuff again down in the video description. Upcoming events, we still have SQL Saturday, New York City taking place in the Microsoft offices in lovely Times Square in Manhattan.

It would be a great time. You can come, you can take, we can take selfies. I don’t know, we can do whatever cool fun stuff people are still allowed to do at conferences these days. Barring any, of course, code of conduct breaches. We don’t want to do that.

We want to have a nice family friendly time at SQL Saturday. With that out of the way though, let’s talk about table variables and logging stuff. So here is pseudocode.

And you know what? You just reminded me that I need to fix a small typo in here before I keep talking. So we’re going to do that and we’re going to pretend that didn’t happen and then we’re going to look at the rest of this stuff. So let’s say that this is our pseudocode and like reasonably intelligent people, we are going to, within the context of our store procedure, set no count in exact abort on.

Then we are going to begin to try. Every day I begin to try. Sometimes things happen along the way that interrupt that. And then we are going to end try and, well, you know, there are a lot of reasons to end trying, I’ll tell you that.

But then in between all that, we have a begin transaction and a commit transaction. Now, of course, you don’t want to really need to do this for a single query. If you have a select or an update or a delete or an insert, you don’t really need this, right?

Because SQL Server is going to be working in auto commit mode where that query will happen within its own transaction anyway. But if you have a group or if you have a flock or a murder of transactions, of queries rather, that you need to put in a single transaction because they all need to complete or not complete as one group. Like Wemmings, they either need to like make it to the top of the hill or fly off the cliff together.

Then you would want to do this. If within this transaction, you want to figure out where along the way you have done things and how long they took and how many rows are affected and things like that, then you can log that stuff to a table variable. And if you hit an error or in like, you know, you like, you know, you hit an error and all this stuff rolls back, then you can still put that data from that table variable into a logging table that you can review later.

You don’t just have to return it out to like whatever client is running down in the commit transaction or rather down after the commit transaction in the begin catch block. We will, of course, do this. Say if trend count is greater than zero, we’re going to roll stuff back and then we’ll insert into our logging table whatever data we have logged in our table variable that has survived the rollback. Because remember, we don’t roll back things that got inserted or updated or deleted from table variables here.

That table variable will be alive until we do this. We can put that into our logging table in the catch block and then review that actual logging table later. You can put all sorts of like good information in here, you know, proc ID, error number, error line, error message, all that other stuff.

There’s lots of things that you can put in there that will make life somewhat easier for you when troubleshooting a problem with a procedure. One thing that I’ve not really come up with a good way to manage is like logging the data that was in there. Like if it’s a small amount of data, it’s not a big deal.

But if you’re doing this for like ETL and you need to move millions of rows around table variables, table variables are just going to hurt more than they help. So probably don’t do that. The second way that you could do this is if you have a store procedure that does something like this where, and again, you don’t need to put like, like wrapping single queries and this stuff is not really useful.

But if you have like groups again, like just like the last one where every query in the procedure had to go and like, you know, ride or die. If you have groups of queries, maybe not like the whole list of queries, but like, you know, groups of queries where along the way, like in all of these do stuff blocks need to ride or die together. Let’s say there’s a, there’s like two or more queries in here that need to complete and, you know, do that stuff.

And you need, and you want to log progress for each query in here, then a table variable would still be your friend. Because if anything happens within any of these down here in the catch block, we can still do this. If, and this is a big, if you are only logging stuff around each transaction, meaning like, let’s say that like before each begin transaction and after each commit transaction, you’re like set, you know, current step.

Equals, you know, transaction one. And then after the commit, you’re like set current transaction equals step two. Then the table variable becomes less useful because it’s not logging anything within the begin transaction commit.

So there’s like the way of thinking about this is anything that’s happening within a transaction could be useful to log to a table variable. If you’re going to do something with it, otherwise it’s probably not. Otherwise you could probably either don’t need a table variable or you just don’t need to be logging stuff, I guess.

This is the easy way, easy way of saying that. But the key thing here is that if you’re not, if you’re not logging, if you’re not doing stuff within each of those transactions, then you can still do the logging down here if you want. Right.

Like that’s easy enough. You just pull out whatever data came along with that. But, you know, for this part, if you are logging stuff about each step between the begin transaction commit, then you would want to put the stuff into the logging table from the logging table variable. And I am not sad to say that this is the very end of where table variables are useful for logging errors, rollbacks and data about things.

At least in my experience, practically speaking, you could probably overly engineer other, you know, solutions to do things like this. But the table variable will not be necessarily useful or even required, will not be a necessity for doing that. That would be your choice to use a table variable when you just didn’t need to.

You could have just used regular variables and you could have just logged very simple, easy information about the error you hit, the procedure you hit the error in, all that other stuff where you didn’t need to put that in the table variable. You just chose to do that for some weird reason, because you are a white knight for table variables and you, you just need to let them, you just need to make them shine. Right? You need to force them to shine like a, like a boy band, just manufacture them being good at anything.

Anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something. I hope that you will not manufacture use cases for table variables. I hope that you will only use them when they are necessary, required and pertinent to the solution at hand.

And yeah, in the next video, we will talk about the thing that really matters when you are choosing temporary. And that is, of course, performance. We’re going to go over some material that I covered in a video somewhat recently that makes sense in this context as well. So I will see you then. And until then, I hope, I hope you are smiling.

Hope you are a happy camper, just like me.

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.

All About SQL Server Stored Procedures: Plan Cache Pollution

All About SQL Server Stored Procedures: Plan Cache Pollution


Video Summary

In this video, I delve into the intricacies of temporary tables and their impact on SQL Server’s plan cache, specifically how they can lead to plan cache pollution or an abundance of query plans. I walk through creating and executing stored procedures that use temp tables in various configurations, demonstrating how these operations can result in multiple entries in the plan cache. By understanding this behavior, you’ll gain valuable knowledge for managing your SQL Server environment, even if it doesn’t directly dictate your choice between temporary tables and table variables. This is part of our ongoing series on SQL Server performance optimization, with future videos focusing on practical performance considerations to help you make informed decisions about these critical components.

Full Transcript

Erik Darling here with Darling Data, and we are going to, in this video, continue our joyous journey into SQL Server Store procedures, and we’re going to talk about how temp tables can cause plan cache pollution, or lots of query plans. The thing that I, two things that I want to say about this up front, one, this doesn’t affect query store, because query store doesn’t care about these things, and two, that I don’t care about the plan cache. I used to love the plan cache. I used to do a lot of work on SP Blitzcache to, like, get in there and find stuff and dissect that XML and, like, really, like, analyze plans. And then the more I did that and the more I used the plan cache, the more I was like, wow, this plan cache is three hours old. What am I going to talk about? What am I going to talk to you about? What, you want to know, like, why things were bad yesterday or a week ago? Get a monitoring tool, bucko. Like, I just, I just have a very hard time finding much utility in it all in the plan cache, aside from when, perhaps, query store settings are not capturing certain query plans. Like, with query store, you can set it to capture all, which means everything, which means everything, which is too much for most people, or you can set it to auto, so that some internal mechanisms figure out what plans belong in the plan cache. And then there’s, like, 2019, I think, introduced all sorts of, like, query store capture policy. So you can set specific things on, like, execution, CPU duration, things like that, to figure out which queries you’re going to allow to end up in there. So I do want this to be, this, I want you to file this under, like, SQL jeopardy, like, good knowledge to have, but maybe not knowledge that’s going to be important for you understanding when to use a different type of temporary object. This is not an excuse to use table variables. Please don’t take it as such, because I will come to your home and smack you until you cry, and no one in your family respects you anymore.

So, with that out of the way, if you would like to avoid that situation, you can get a membership to the channel. I don’t know if I’m allowed to do that. I think that might be extortion, or racketeering, or one of those, one of those RICO predicates. Anyway, there’s a link in the video description for you to do that. If perhaps someone else has extorted you, or racketeered you, or whatever, and you just have no more money, your pockets are turned inside out, you can feel free to like and comment and subscribe, or else. And you can ask me questions, and you can ask me questions privately that I will answer publicly on my office hours episodes of the Darling Data Dandy Hour, or whatever. I don’t know.

If you need help with SQL Server, and you want someone to threaten SQL Server into subservience and performance yeses, I am a consultant, and I consult on all matters related to SQL Server performance, and more. Health checks, hands-on tuning, responding to performance emergencies, and tuning your developers, actually. I will tune your developers, so that you don’t have performance emergencies anymore. You can avoid those in the future. You can finally sleep through the night. No more pagers going off, or whatever happens.

I don’t know. Maybe it’s too soon for that one. Anyway, if you would like to get some SQL Server training from me to you for the rest of your life, for about $150, you can go to training.erikdarling.com, where you will see the full expanse of my hand. And you can use that discount code. And again, there’s a link down in the video description, so you can get all that stuff. SQL Saturday, New York City 2025.

You can come to me. You can come see me in person. You can see this Adidas shirt in person. Maybe it’s not this specific one, but an Adidas shirt. I’ll be there serving lunch, smoking cigarettes, maybe getting drunk out back. Who knows? But anyway, come to the event. It’ll be a great time. With that out of the way, let’s talk about these plan cache shenanigans with temporary objects.

Now, what I’m going to do is set up a couple of store procedures and run them in a few different windows, and then run a query that looks at the plan cache. So the first one, and there’s an alternate version of this one down here. We’re going to talk about that in a minute. This first one is called a spid. And what this thing does is creates a table called a spid and inserts a value into it.

And then we have another procedure down here called no spid, which creates a table, inserts a value into it, and then executes this store procedure. This, like, a spid, right? So this store procedure executes a store procedure above it. There’s an alternate version of this where I rename the temp table to match the name of the procedure.

One thing that I find is very, very useful to avoid these types of problems is to give your temp tables very unique names. Do not just name them all T or P or A or C or D or A1 or T1 or something. I have, of course, been guilty of that in the past, so I’m not, like, busting you down about it, because I’ve done it too.

But the longer you live, the longer you learn, the more you realize unique names for temporary objects that are descriptive of their task are often a good thing. So I’ll show you that second, though. And the second way I want to show you this is with a slightly different setup, where we have this not internal store procedure, which sort of is, I guess, kind of weird.

But this is just going to insert values into a temp table, but the temp table is going to be created down here. But I’ll show you that in a second. And I have this one equals select one here just to prevent simple parameterization.

I forget why I stuck that on there, to be honest with you. I don’t think it’s necessary for the purposes of this demo. But then we have this store procedure up here called internal, which creates a temp table called internal, selects a count from it, and then executes the store procedure not internal that we just looked at above. Quite frankly, I do believe I named those backwards.

But anyway, let’s make sure that we have all these in place as, well, I mean, I was going to say as God intended, but it’s pretty much how I intend. But for all intents and purposes here, I guess I am God. We’re also going to clear out the plan cache.

I know I just did that, but I like to make extra sure. And then what I’m going to do is I’m going to run this, both of these store procedures in this window. I’m going to run both of these store procedures in this window.

And I’m going to run both of these store procedures in this window. So I run these store procedures three times across three different spids. Now, we’re going to look in the plan cache, and we’re going to use a very specific query that does a little bit of an extra thing, where we’re going to cross-apply to sys.dm exec plan attributes.

And we are going to look for the attribute optional spid. Okay? And we’re going to see the values for that up here.

Okay? Attribute and value for optional spid there. And looking at the results, what we’re going to see is two references to internal and one reference to no spid with a value all of zero. So, like, if you just have a temp table in a store procedure and you call that store procedure, SQL Server doesn’t have to do anything interesting with it.

So, as soon as you reference that temp table with a store procedure that gets called by the main store procedure, or you call another store procedure that creates a temp table with the same name, SQL Server has to figure out some way of differentiating things. Because it’s the plan. It’s the plan cache, and the plan cache is full of goblins.

And what we’re going to see down here is three different plan cache entries, each for the sub store procedures. Okay? And each one for optional spid is going to have the value of the session ID that called it.

So, we have three from session 69. I didn’t do that on purpose, I swear to you. I couldn’t possibly have.

That’s going to be that first window that we executed stuff from. Then we have three with 74. That’s going to be the second window. And three with 75, and that is the third window.

So, again, file this under things that are good to know, not things that should dictate how you choose between temp tables and table variables. Before we go, I want to show you one additional piece of good news. And that is that if we run that first demo, right?

But we create a different version of no spid where we give the temp table that gets created in here a more unique name. So, rather than this thing being named a spid like it is in this one, we’re going to name this no spid, which matches the name of the procedure. Then we’re going to run this.

We’re going to clear out the plan cache and run this again. And we’re going to run just no spid here. Oh, wait. You know what? I have to do that down here first, don’t I? I do. We’re going to run no spid here first.

We’re going to run no spid here second. And we’re going to run no spid here third. And now, when we look at the plan cache, both of these are going to have a value of zero, right? So, unique temp table names do help reduce this problem.

But it doesn’t matter if you have a store procedure that references a temp table from another store procedure. Okay? So, if you have this outer procedure, you create a temp table, and then inside your other store procedures, you do stuff with that temp table because that’s perfectly valid.

It’s all in scope. Then you will end up with the optional spid thing. If you end up with the optional spid thing because you created temp tables with duplicate names across store procedures, an easy way of fixing it is to give your temp tables more unique names.

Again, this is not a good reason to pick table variables which don’t cause this outcome. I’m not going to say cause this problem. I’m not going to say cause this issue because I don’t consider it much of a problem or an issue given how crappy the situation most plan caches are in generally.

I suppose you could somewhat improve the situation of your plan cache by following my advice. But, you know, whatever. It’s the plan cache.

Use query store anyway. But this is something that is good to know about because you might be one of those people who still has that awful folder full of scripts from, like, dates going back to, like, 2002 that mined the plan cache for certain things.

And you might run them and you might see lots of query plans for procedures that have temp tables in them. And you might wonder why and say, dear God, I thought every query just got one plan. What is happening?

Microsoft has betrayed me. How could I possibly overcome this betrayal? Well, there’s ways. There’s ways.

Here’s your ways. Give your temp tables unique names. That’s the easy way to do it. But that doesn’t help if you are referencing a temp table from one store procedure in another store procedure. It doesn’t matter how unique the name is because you’re just calling back to that first one anyway.

Maybe multiple procedures and queries will do that. I don’t know. It’s all wild. Anyway, thank you for watching. I hope you enjoyed yourselves.

I know you learned something. But you learned something that is just good knowledge. This is not knowledge that you will use to dictate use of temporary objects. In the next video, we’re going to talk about performance.

And that is going to be what you will use to dictate your choice between temporary tables and table variables. This is not what we’ll do. The previous video on recompiles probably isn’t what’s going to do it.

The next video on performance, that’s what’s going to do it. All right. Cool.

Thank you for watching. Thank you for watching and fully comprehending everything that I say. I know that reading comprehension is somewhat difficult. But hopefully listening comprehension is much easier because I speak in a clear, precise, and authoritative tone.

All right. The dad you never had. All right.

Well, 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.

All About SQL Server Stored Procedures: Nested and Autonomous Transactions

All About SQL Server Stored Procedures: Nested and Autonomous Transactions


Video Summary

In this video, I delve into the intricacies of nested transactions in SQL Server, addressing a request from viewers who wanted to understand how these work and when they might be useful. I explain that while SQL Server behaves differently compared to other database engines like Oracle, it still doesn’t support partial commits within nested transactions as one might expect. Instead, all changes are rolled back if any part of the transaction is rolled back. To illustrate this concept, I create a simple stored procedure and demonstrate how transactions work in practice, showing that even though you can begin and commit multiple transactions, rolling back an outer transaction will undo everything inside it. This video aims to clarify common misconceptions about nested transactions and provide practical insights for SQL Server users.

Full Transcript

Erik Darling here with my second take recording this video. I hit a new professional low where I actually recorded about half of it and then somehow ended up hitting the stop record button and didn’t realize it and just kept talking. And then when I was done, I went to hit stop record and I was like, oh, yeah, that’s fun. So anyway, in this video, I’m going to hit stop record. In this video, we are going to get back into talking about store procedures. Now, I talked about transactions a couple of times, a couple of ways, but one of them in this series, another one was just sort of a funny short video about someone saying while ADAT trancount is greater than zero, roll back, which is just amusing to me. I have gotten some feedback that people would want to know exactly how nested transactions work and how you might be able to actually get a nested transaction to nest because SQL Server behaves a lot differently than a lot of other database engines when it comes to nesting transactions.

I think probably the prime example is Oracle, which does allow for partial commits in nested transactions, where SQL Server, well, you get, y’all don’t get rolled back when you roll back the transaction. We are not going to talk about save points because screw that. And yeah, that’s about it there. Anyway, if you would like to support this channel, if you sign up for a million dollars, I’ll talk about save points. If you barring that, not getting into it. You can use the video, the link in the video description to become a paying member of the channel for as few as $4 a month. You too can support a starving SQL Server consultant.

Then maybe I can stop answering questions about why my face looks skinny lately. If you like the channel, but maybe not enough to put a ring on it, you can like, you can comment, you can subscribe, and you can ask me questions privately that I will answer publicly here on my Office Hours episodes. It is not a podcast. Most vociferously, not a podcast.

If you need help with SQL Server, I am, they don’t call me Eric Reasonable Rates Darling for nothing. My rates are reasonable, and I am, again, editorially presented with, by Beer Gut Magazine, with being the best SQL Server consultant in the world outside of New Zealand. So, I don’t really see what you have to lose there.

If you need SQL Server training, and you don’t want to pay, like, two grand, you can get online for about $150. It’s about 24 hours of content, beginner, intermediate, and expert, maybe even some beyond expert stuff. And you get that for life. You do not have to subscribe to that.

You just sign up, and you’re in. It’s just, that’s it. You’re officially a dues-paying member, and you’re allowed in the clubhouse whenever you’d like. SQL Saturday, New York City 2025, is taking place on May the 10th, with a performance pre-con by Andreas Volter on May the 9th. You are cordially invited to both, and you are also cordially invited to bring me gifts.

You can bring me presents, preferably in the form of low-value currency. So, no hundreds and fifties, just stuff that’s easy to spend at the bodega. So, keep that in mind.

But with that out of the way, let’s talk about nested transactions. Now, SQL Server does have the concept of autonomous transactions. Now, I had that window open already. Good for me.

Now, you might look at the data on this blog post, and you might think, golly and gosh, that’s old. There must be a better way. Guess what? It’s not. You still have to do all this stuff.

Now, this is from back when SQL Server, rather when Microsoft, used to have good SQL Server blogs. If you’ve read a SQL Server blog post lately, you might notice that they’re not good. And they used to, way back when, look at this, back to 2006.

What were you doing in 2006? What was I doing in 2006? Being young, having fun, life worth living and all that stuff.

But Microsoft used to have good SQL Server bloggers. So, I would suggest reading this content before Microsoft makes it disappear. Because one thing Microsoft is famous for is making good stuff disappear and replacing it with crap.

So, please, you know, support your local internet archive or something. Because this stuff ain’t forever anymore. But this post walks through the concept of autonomous transactions, how to make them work by using a loopback linked server.

If you come down here, you’ll see some of this stuff. That is a really aggressive use statement up there. I don’t know if I agree with that.

But you’ll see where they create a linked server called loopback that just connects to your server, right, which is add at server name. And then you’ve got to do some stuff. And then you can get transactions that do partially commit doing that.

You can’t do it really any other way. Unless you want to write absolutely bonkers stuff using table variables and save points and other things. Where, like, it’s so obtuse and edge casey that I don’t want to write that code because I feel like I would get something wrong with it.

And one of, like, three people in the world who would know when that code is wrong would make fun of me. So, we’re not going to do that. So, I will hopefully remember to put that in the video description or get yelled at either way.

But the way that a lot of people think nested transactions work because, like, when you look at nested transactions, it makes sense for them to work like this. But they don’t. And this does work in other databases like Oracle.

I think there’s even a mention of that in the Microsoft post. At least I saw the word Oracle and there weren’t, like, devil horns on it. So, I assume they said something okay about it. But the way that you would expect it to work is, like, begin a transaction called T1.

Do some stuff. Begin a transaction called T2. Do some more stuff. Commit transaction T2 and just have this be, like, out of the picture, right? Like, you saved your changes from this.

You’re done. And then roll back. And then, like, if you wanted to roll back T1, T2 would be left alone. But that doesn’t happen. SQL Server does not do this. SQL Server rolls back everything.

There are no partial commits, right? At least none that stick around in Survivor rollback. So, the way that I want to show you that, like, that concept in SQL Server is I’m going to create a simple table and a simple store procedure. And this store procedure is just going to do, well, I mean, I guess essentially three things.

It’s going to begin a transaction and commit a transaction. And in between that, it’s going to do two inserts into this table just based off whatever values I pass in. And then just to not get a primary key violation, I’m going to add one there.

Outside of the store procedure, I’m going to hopefully remember to begin a transaction called T2, run the store procedure, run a select to show you what values ended up in there, then roll back T2 and show you what values are in the table afterwards. So, if we do this and we run this, we get exactly, we get, like, a query demo proving exactly what I just told you.

Well, while T2 is an open transaction, we can see these two rows have committed to the transaction table. We have both rows that the store procedure inserted in there and committed, right? Like, this thing did begin transaction commit.

We didn’t stop at all. Like, the entire procedure executed. And then later, when we rolled back transaction T2, that undid the T1 transaction inside of the procedure. So, you can’t do that.

Like I said, you can get some of the aspects of an autonomous transaction if you use table variables and write really complex code. I don’t recommend it. You will spend more time dealing with weird issues than you will be happy that you wrote it.

So, maybe don’t do that. Like, save yourself some pain. I mean, you know, like, if you want to get autonomous transaction behavior in SQL Server with as little pain as possible, and I say as little pain as possible because you’re still dealing with linked servers and that’s absolutely no fun, then the instructions in the post that will be, remember, in the video description will walk you through that and how to do that.

So, that is the least painful way, at least, that I’ve come across. I’ve seen various people try to get the autonomous transaction thing working with table variables and save points and all this other stuff, but I’ve never seen a happy person try to do that.

So, I want you to be happy out there. I want you to be happy, bright, sunshiny people who have great weekends and don’t try to do overly ambitious, borderline stupid things with their databases because we all know how that ends up.

Anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something.

And I will see you in another video, another time, another place, another you, another me. It’ll be beautiful, though. Well, hopefully we’ll remember each other. 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.

T-SQL Tuesday 185 Wrap Up: Video Star Edition #tsql2sday

T-SQL Tuesday 185 Wrap Up: Video Star Edition #tsql2sday


Video Summary

In this video, I recap the engaging T-SQL Tuesday 185 event where community members were encouraged to share their thoughts through videos rather than blog posts. The response was quite diverse and entertaining—ranging from humorous technical mishaps to insightful demonstrations and heartfelt reflections. Highlights included Rob’s creative green-screen trick in SQL Server Management Studio, Andy Levy’s exploration of the Object Explorer Details feature, and Andy Yoon’s practical stored procedure for expanding view references. Other submissions covered topics like flat file wizard capabilities, content consumption preferences, empathy as a technical skill, and personal experiences with presenting and blogging. It was fascinating to see how these videos provided not just information but also a glimpse into the personalities behind each contribution.

Full Transcript

Erik Darling here with Darling Data, and this is going to be my T-SQL Tuesday 185 wrap-up video in which I asked the nice folks out there in the SQL Server community to record it, rather than write a blog post about a specific topic, to just record a video about anything. And I got, I don’t know, seven or so pingbacks on that. If anyone out there recorded something and didn’t ping me back, sorry. If you don’t tell me, I don’t know. So, anyway, first, you know, in true he whom the gods would destroy they first make mad fashion, the video that I recorded to invite people, I had a weird little audio glitch going on. And I thought that I fixed it, and then I didn’t fix it, and then I didn’t get a chance to re-record it, and then, I don’t know, I was fully expecting at least one of the video submissions. to make fun of my bad robot voice in the video, but everyone was just, it was kind enough to not make fun of my slight technical difficulty. I’ve managed to avoid a lot of those in recent videos, so, I don’t know, I guess, I don’t know, maybe I’ve earned it. Anyway, our first video came in, of course, I’m going to say this video came in first, but only because Rob is cheating with time zone magic.

Usually he’s cheating with normal magic tricks, but this is just time zone magic. And Rob’s video, he talks about the cool mappy scroll bar on the side of SQL Server Management Studio. Of course, that’s available back, I remember when that first came out, but, you know, at first I didn’t like it because it was, like, too big on the side, and, like, when you hover, like, this, I know it’s an option, but, like, you hover over it, and you get, like, this, like, giant, like, preview of the text in there. And, like, it just, like, got in the way a lot with stuff, you know, it’s, like, there’s a certain amount of tooling where it’s just, like, sometimes these, like, pop-up things are helpful, and then sometimes it’s just, like, obtrusive. But with SSMS 21, I think I’ve been liking it a little bit more. I don’t know why. Maybe it’s the dark mode, who knows.

But Rob actually did a very cool trick where he green-screened himself into SQL Server Management Studio. I might steal that from you someday, Rob. I don’t know when or why or how, but I’ll figure it out and do that. Anyway, thank you, Rob, for this lovely video. Next up, we had Sir Andy Levy talking about one of actually, one of my favorite things in SSMS that, this is, like, one of those things that, like, actually kind of wows clients when I’m on the phone with them, is the Object Explorer Details. So, like, you can either, like, right-click and go to Object Explorer Details, or if you’re in SQL Server Management Studio, when you, like, highlight a database or a server or something, and you press F7, that’s F like Frank 7, you get this new thing that pops up that gives you all sorts of neat details.

And one of my favorite things about it is, like, just to give an example, if you have a table with a bunch of indexes on it, and you want to script out all the indexes and just see what’s in there, if you hit F7 and you go to Object Explorer Details, you can actually multi-click stuff and right-click on everything that you’ve just multi-clicked, and you can hit Script, and you can get all the indexes rather than clicking on, like, one index at a time and scripting it.

It’s very convenient for many things. So, good job there, Andy Levy. You read my mind, or something. Next up is Andy Yoon with an actually very helpful stored procedure.

I would be terrified to run on some of my client environments. It is called SP Help Expand View. And what SP Help Expand View does is, if you have a view with a bunch of nested views in it, it’ll go through and find all the view references.

And there’s an optional mode where it will give you a count of, like, how many times things are referenced in the view. So, that’s a very, very cool thing to have. Like I said, I’d be a little afraid to run it and get, like, 90 columns of nested views back.

But if you’re feeling brave and bold out there or just particularly pioneering in one of the environments you work in, I would highly recommend using this to help yourself untangle the nastiness of nested views. So, well done, Andy.

Well done. All right. The next submission I had was Steve Jones pushing the boundaries of cutting-edge technology with testing the flat file wizard, in which Steve discovers that the flat file wizard can handle multiple delimiters, not just commas and fixed width, but also pipes and some other stuff.

And then at the very end of the video, Steve submits a pull request to the Microsoft Docs site where he makes some improvements to that. So, Steve really, like, pushed the envelope of not only data engineering, but also DevOps and, I don’t know, something else probably. But good job, Steve.

Steve, we now can use the flat file wizard with a bit more confidence, I hope, when we’re dealing with our flat files. All right. The next submission I got was from Deb, whose background, for some reason, looks nothing like Andy’s background.

At least last I heard, they’re still married. I hope I’m not messing anything up there. But she is asking some questions about stuff.

She wants to know how you consume content. She wants to know the type of content you prefer. She brings up some good points about videos where, like, it’s harder to watch videos. It’s harder to sit down and dedicate the time to, like, sit there and watch one thing and just, like, absorb that.

If you have something written, you can, like, go to it and come back to it and sort of, like, follow stuff around and, like, you know, take bites as you can. With videos, it’s a little bit harder to do that. I often find myself with, I mean, anything audio related, you know, it’s not just videos where there’s, like, a visual component.

But, like, I’ll find myself, like, I’ll put something, like, on a podcast. I’m like, oh, I really want to hear about this. And, of course, I’m sitting at my computer.

So I’m nip, dip, dip, dip, dip. And, like, you know, like, 45 minutes goes by and I realize I’ve absorbed nothing from over here. So valid points. I get it.

But, you know, also talks a bit about how the bots out there are stealing the words and not giving credit for the words. And, I don’t know, I think probably Sam Altman and, by extension, Microsoft owes all of us a very big royalty check for all the training material they’ve gotten from us. I’ve got a copyright on my blog posts.

I don’t know about you. I’m waiting for my royalty check in the mail. All right. Next up, our dear friend Mala, who is, oh, look out. Look at tiny Mala in the corner.

Why is Mala hiding? There’s Mala. Wonder why. Wonder why Mala is so small over there. But she has a great video about empathy being a technical skill.

Hopefully one that I learn someday. I would love to someday empath myself, empower myself with empathy or something like that. But good job there, Mala.

We could all stand to be a bit more empathetic in the world. Especially to people who have audio technical issues when writing a recording to invite people, or rather, recording a video to invite people to record videos. So, I guess the SQL community has a bunch of empathy in it.

All right. All right. And the final one was from our dear friend, Making Plans for Nigel, who got all dressed up, wore a Darling Data t-shirt. One of the few people who, I guess, didn’t donate the one they got for free from me at a conference to a homeless shelter.

So, thanks for that, Nigel. And recorded a lovely video from his backyard talking about his experiences with sort of like presenting and blogging and getting turned down from conference. It was an expansive video.

There are big feelings in this video. A lot of big feelings. But he is curious because he does put a question out there. Would you like to see more of these?

And, of course, Nigel, we would always like to see more of you and your fabulous backyard. All right. So, that’s the wrap-up. I hope that everyone out there who recorded a video enjoyed recording the video.

Maybe it will spark some more recording magic from you. I do like watching videos and getting a sense of the person behind all the content. But maybe I might be somewhat alone in that.

I don’t know. Anyway, thank you for watching. And I will, I don’t know. I don’t know when the next time I’m going to host a T-SQL Tuesday is. I think we’re rate limited to like once a year. So, you might not see me again until, what is it, 2026 is next year?

Good God. Someone stop this thing. Anyway, thank you for watching. 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.

A Little About Index Sort Order And The Order By Clause

A Little About Index Sort Order And The Order By Clause


Video Summary

In this video, I delve into the fascinating world of SQL Server indexes and query plans, specifically focusing on a phenomenon known as “surprise sorts.” You’ll see how different indexing strategies can lead to unexpected sorting operations in your queries. I explore this concept by running a series of queries against the Stack Overflow database, demonstrating how the order of columns in an index impacts whether or not SQL Server needs to sort data during execution. This video is perfect for anyone looking to deepen their understanding of query optimization and indexing techniques, as it provides practical insights into avoiding unnecessary sorts that can impact performance. Whether you’re a seasoned DBA or just starting out, this content offers valuable lessons on how to craft more efficient queries and indexes.

Full Transcript

Look at you. You look great. You look great, smell great, everything about you. Great, great, great. Erik Darling here with Darling Data. Me and my pal Bats been chatting. We had an interesting client call where, you know, when I talk with people about SQL Server, SQL Server performance. We talk about a lot of stuff. stuff to do with queries and indexes and query plans and the way different things you do in your query and design your indexes has an effect on the query plan that you ultimately end up getting, which should also should all be at least fairly clear to my distinguished audience. But, you know, some people need a little bit more help and guidance than others. That is what I’m here for. So in this video, we’re going to talk about a sort prize. Now, now, keep in mind, this is not like a sort sort prize, like, hey, you won. Congratulations. You get a thing. Here is your honorarium of some variety. This is a surprise sort. And we’re not, this isn’t going to cause a big performance issue today. This is, we’re just going to look at how index, like the intersection of indexes and querying and how you can sometimes end up with a sort that you might not expect in your query plan. But before we do that, Bats would like to remind you that you can become a loyal paying member of the channel to say thank you for all of the hard, diligent work that I do producing this content. There is a link down in the video description there where Bats is pecking away, where you can, for as few as $4 a month, support your local SQL Server enthusiast. If you have perhaps engorged your Bats engorged your Bats with Pez candies, you’ve spent all your money there, you can do other things to support the channel. You can like, you can subscribe, you can comment. And if you would like to ask me questions that I will answer during my officially branded Bats Maru office hours, you can go to that link, which is also in the video description.

You can ask me questions that I will answer. If you need help with SQL Server beyond what you can get from mere YouTube videos, you can do all, you can hire me to do all sorts of things that people find useful. Bats is being a little, a little cranky today. I can do health checks, performance analysis, hands-on tuning of your SQL Servers, helping you with SQL Server performance emergencies, and of course, training your developers so that you don’t have those performance emergencies anymore. These are all things that, according to BeerGut Magazine, I excel far beyond anyone else in the world at. So, you are free to hire me to do all of these things. And you can rest peaceably with the knowledge that you have hired a BeerGut Magazine certified SQL Server consultant.

And as always, my rates are reasonable. If you would like to get some high quality, low cost SQL Server training from me and you old bats here, you can get all 24 hours of mine to fill your brain with for about $150 US dollars. And that will last for the rest of your life. All you have to do is use the coupon code right there at the link up there, which is also down in the video description. And gosh darn it, you can, you can start being as good at SQL Server as batsmaru.

SQL Saturday, New York City, 2025. That is this year. That is just a couple months away now. Coming up, May the 10th, with a performance tuning pre-con on May the 9th. I highly suggest you attend both. And you hang out with me and become my best friend. Maybe, maybe that’ll be the start of something beautiful. Who knows?

But without it in the way, let’s talk about surprise sorts, because they’re interesting things. Now, we’re going to run a query with a few different things going on in it. And we’re going to use this query and the index that we have available.

And then we’re going to, I’m going to show you what happens with a slightly different index. So we’ve got right now this index up here. Zoom it would be so kind as to zoom. There we go.

We’ve got this one here where reputation is in ascending order. Now, for those of you who are new to this whole thing, because the users table in the Stack Overflow database has a clustered, the important part here is clustered primary key, on the ID column.

The ID column is a hidden key column. It is a hidden key column because this is a non-unique index. You notice that there is a distinct lack of a word, the word unique, in here.

So because this is a non-unique index, the ID column, Zoom it would be so kind as to erase the squares instead of just having me click buttons mindlessly. The ID column is hanging over here as an additional key column. If the index, well, that D was a little aggressive, huh?

Let’s dot that I. If this were a unique index, then the ID column would be hiding, well, somewhere in this region is an included column. But since this is a non-unique clustered index, it is an additional key column, which means that this index is sorted by the reputation column first.

Right? So all of the values for reputation are sorted from one to whatever John Skeet is, one million and something. And for all of the duplicates, right?

Because we index all the data. So let’s say for the million or so people who have a reputation of one, the ID column is in order for that. But as soon as we go to reputation two, the ordering of ID resets and we start from whoever has the lowest ID to the highest ID within the next range of values.

So we have an index where reputation is in order and an index where ID is in order within all of those ranges of reputation. So we would expect to be able to order things, have an order by in the query that helps with all sorts of stuff, helps us avoid sorting data. Now, like I said before, this isn’t going to show a big performance issue.

This is just going to show you some behavioral stuff. So if I select the top 1,000 rows from the users table and I order by reputation descending, right? Just reputation descending on its own here.

Then we get a backwards scan of this index, right? Scan direction is backwards. But we don’t have to sort any data.

We have a top and we have a scan. We do not have a sort operator in our query plan. SQL Server did not have to acquire any additional memory grant in order to put this data in the order that we have asked for it. If we run these two queries, well, the reason why we might do something like this is because the reputation column is not unique.

Remember, we talked about that when we were talking about the index definition. And if we have any ties in the reputation column, we might want to add a tiebreaker in the form of this unique ID column to our query so that we have a way to uniquely identify the top 1,000. Otherwise, if we could get duplicate reputation, not replication, we could get sort of unexpected results ordering by a non-unique column.

So let’s run these two queries. And let’s look at what happens. Now, you’ll notice that for the execution plan where we order by reputation descending and ID ascending, we have a top-end sort.

In the query plan where we have reputation, so let’s put a little square around that here, make it obvious. This is reputation descending ID ascending. In this query, we have a top-end sort.

In this one, we just have a top. We are back to our original plan. Now, the reason for this is somewhat complicated or maybe not incredibly intuitive to folks out there.

And let’s try to explain it well. If you look at the properties of this index scan, you’ll notice that we do not have a direction on this one. If you look at what happens, there’s no, like, we didn’t have like a backwards scan.

If we look at this one, the backwards scan will be back. So this one has the backwards property. This one is an unordered scan of the table.

That’s why we have to sort this over here. And, of course, the sort operation is ordering by reputation descending and ID ascending. So the question is, why, when we sort by reputation descending and ID ascending, do we need to sort the data?

But when we sort by reputation descending and ID descending, we do not need to do that. Well, what it really comes down to, and if we look at the results over here, it might be a little bit more obvious. I do have to do a little bit of surgery on this to get both of these query panes to the right place.

And, of course, we need to get to around row 276 for this to be incredibly obvious or for this to start to become obvious. So let’s look at both of those. Oh, come on, SSMS.

You’re really making a fool out of me here. So 276 or so has the first duplicate that I could find in the results. Yes, I did scroll through and look for them.

So we have the reputation 160303 here. Right? And that’s the same for both of these. But you’ll notice that the order of the IDs is slightly different for them. In the top query where we’re ordering by ID ascending, we have 1-9-6-7-9 first and then 2-0-6-4-0-3 second.

In the bottom query for 1-6-0-3-0-3, we have ID in descending order. So we have 2-0-6-4-0-3 first and 1-9-6-7-9 second. Right?

So clearly those two values flipped. Now, the way to think about why we need to sort the data in the top plan but not in the second plan does come back to the execution plan. So, again, the properties of the scan with the sort does not have a direction on it.

Right? There is no ordered. When you look at the ordered attribute, it says false. So we just read through stuff and found it.

The reason for that is because imagine that you are the SQL Server engine. Right? And you are reading through the index over here backwards.

Right? So you’re reading. You’re doing a backwards scan. So let’s just pretend that, like, this is our B-tree. And over here is the, like, ascending end of our B-tree.

And over here is the descending end of our B-tree. So the backwards scan starts over here and starts reading things this way. Right?

So we’d be reading through this index in descending order. And then all of a sudden we would get to, like, we’d be, like, you know, we’re ordering by reputation descending. We’re reading through the index in descending order. And we’re trying to, like, you know, we want to order by ID ascending.

We would get to that, like, 160303 reputation. And then we would have to, like, do a U-turn and be, like, no, now we need to sort it this way. Right?

So SQL Server, like, it can’t really do that. Like, that’s not really how B-trees work. We can’t just, like, start sort, like, reading the index and then, like, backwards order this way and then be, like, ah, but then order the other column this way. Like, SQL Server is not, like, an advanced enough product or rather doesn’t have that advancement in the product in order to do that.

So in the second query where we are, we just, we can just straight up backwards scan the whole thing. ID is already going to be, like, we’re reading through the index backwards. So ID, the ID, the order of the IDs is also going to be backwards reading through that.

So as we’re reading through the descending order reputations, ID is also going to be in descending order. So SQL Server can just chug along that and have all the data straight in the order that it wants for both of those. So that’s why we don’t need to sort there.

Of course, you can write a query that would do that for you if you were to break things up a little bit and do some manual phase separation, as the smart folks out there say. And we were to get the top thousand reputation ordered by reputation descending in an inner query. And then join, remember, we have to get, like, we’re doing the group by here so we get our unique set of reputations back.

And then out here we join back to the users on that reputation. Then we can get the data that we want in the order that we want without sorting it. Right?

And the reason for that is because we hit that index twice. Right? Look at that. We scan into the index over here and we seek into the index here. When we scan the index here, we are doing that.

We are back to doing a backward scan. So we’re reading the data from over here this way rather than over here this way from largest to smallest rather than smallest to largest. And so we do the backward scan here.

We produce the top thousand rows. And then this index seek is going forward. So we’re reading through this index.

We’re joining on reputation. We start with the lowest reputation that came out of there. And we move to the highest reputation that came out of there. So we’re in forward order on this one. And we can avoid having to sort data at all in this query plan because we have two separate reads of the index that happen in two separate directions.

SQL Server could do this for us if it felt like doing a bunch of extra work in the query plan. But I understand a bit why it doesn’t. Now, of course, if we really cared about like we really wanted an index to do that for us, we could create this index because this would be reputation descending and ID ascending.

So what we would have here is an index that you don’t need to read backwards in order to get data from this end to this end because we have the highest stuff over here. And reputation is going to be an ascending order from there. So we can get this plan over here without a sort now.

So depending on how you need to return data with your queries, you might need to think about how you create your indexes and which direction you store your data in. Because sometimes if you need to mix sort like sort orders like this, like reputation descending, ID ascending, you might need to change the way that your indexes are set up or write really much more complicated queries in order to in order to avoid having to sort data. Now, of course, like the client issue that I was dealing with was a big sort and it was taking up a lot of memory and it wasn’t using a lot of that memory.

It was getting a very big memory grant, not really using it. And so we had to think of some clever ways around that problem. And that is what brings us here today is solving problems in clever ways.

We could do the query rewrite and leave the indexing alone or we could change the index. So we have choices as far as making things work. Anyway, thank you for watching.

I hope you enjoyed yourselves. I hope you learned something about, well, either indexes or forward scans or backward scans or some kind of scans. I don’t know.

There’s a lot of scanning going on in here. Anyway, maybe that’s my problem. Anyway, thank you for watching. I will see you in another video another time. Toodle-

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.

Equality, Sort, Range Indexing In SQL Server – When It Doesn’t Work

Equality, Sort, Range Indexing In SQL Server – When It Doesn’t Work


Video Summary

In this video, I delve into the intricacies of equality sort range indexes, specifically when they might not be as beneficial as initially thought. Building on yesterday’s discussion, I demonstrate how these indexes can struggle when your range predicate is highly selective and your ordering elements are poorly aligned with query requirements. By running through several queries and their corresponding execution plans, I illustrate the challenges faced when trying to optimize performance in such scenarios. The video also includes tips for improving query performance, such as using index hints and considering alternative indexing strategies that better align with specific query patterns.

Full Transcript

Your best friend in the entire world, Erik Darling here, to talk to you further about a subject that we broached in yesterday’s video, which is the Equality Sort Range Index. In yesterday’s video, I did say that there are situations where it’s not going to be as great of an idea as it is in others. And we’re going to, we, I owe you at least something for that. So, to sort of generalize a little bit, the problem with this style of indexing comes when your, let’s see, an easy way to put this, when your range predicate is far more selective than your Equality predicate and your ordering element or elements are in a bad order for the way you want to search for things.

It’ll make a lot more sense when I actually show you the demo. So, for now, let’s just, let’s just keep in mind what the topic is going to be and be amazed and astounded and just wowed right out of the seat of our pants when, when I show you what’s going on. But before that, of course, I like doing this stuff.

I like doing this stuff even more when people sign up for memberships. So, if you would like to do that, there’s a link right down in the video description. And for as little as four bucks a month, you can say, hey Eric, thanks for doing all this.

It looks like a lot of work. You’re a real sport. If you do not have four bucks a month, perhaps you have significantly increased your Pez dispenser collection, used eBay for its original purpose, and you just don’t have four bucks, you can do other things that help me become a bigger, better person.

You can like, you can comment, you can subscribe. And if you want to ask questions, fancy little pinky out questions privately that I will answer publicly on this very YouTube channel, you can go to the link above then, which is also in the video description, and you can ask your questions there.

And I will answer them five at a time. Again, I’ve got a bit of a backlog on these, so we’re going to record some of those very soon. If you need help with SQL Server, if asking a question anonymously that gets answered non-anonymously online, you can hire me as a consultant to do all sorts of things with your SQL Server to improve performance.

I do all of these things and more. And as always, my rates are reasonable. If you would like to get some training content from me, carrying on my fine tradition of rate reasonability, you can, again, video description has the fully assembled link, but if you feel like typing, you can go to training.erikdarling.com and punch in the discount code SPRINGCLEANING and you can get 75% off any of my training videos.

Fun stuff there. SQL Saturday, New York City, 2025. That is this year. That is, at this point, let’s, uh, uh, I mean like, really, like, two months away at this point.

So, I, if you’re speaking at them, gosh, I hope you practiced. And, uh, as always, I will see you there. Uh, bright and, bright and oily.

But with all that out of the way, let’s, uh, let’s talk about when this equality sort range index thing doesn’t work out so well. So, uh, because I felt the format of yesterday’s video worked pretty well, um, I have pre-created some indexes and I’m gonna run some queries using index hints to show you what happens when these queries interact with those different indexes.

Uh, so let’s run these two queries. And I’ve got query plans enabled because, gosh darn it, I’ve been practicing. Don’t wanna, don’t wanna disappoint anyone with, uh, unpracticed SQL Server demos.

And you might notice that these, at least, well, one of these queries is taking quite a while to execute. And, uh, it’s gonna continue to take quite a while to execute. So, what these are doing, and the, the difference between these two queries is just in the ordering.

Uh, this one is, of course, ordering by the ID column in ascending order. And this one is ordering by the ID column in descending order. So, for this first query, uh, what it, what’s worth noting here are a couple of things.

Uh, one, we’re gonna pretend we don’t have any useful indexes at first. And I’m gonna show you what happens when either you don’t, you don’t have any useful indexes, or for whatever reason, SQL Server does not choose some useful index that you have.

Uh, let’s just put, like, you could, you could substitute this ID column for like a select star, or select a bunch of columns type thing. And SQL Server might cost using a narrower index out of, uh, out of the equation, because it doesn’t want to do a whole mess of lookups.

All right? So, just bear with me here for a moment. Um, we are forcing the clustered index via this index hint. And we are looking for, in the votes table, vote type ID equals two.

Vote type ID equals two has about 37 million rows associated with it. That is the almighty upvote in Stack Overflow land. And the other predicate that we have on this table is where creation date is between 2013-1201 and 2013-1231.

Now, since this is the Stack Overflow 2013 database, the world ended right here. There are no, there are no rows after this. So, this is the last month of data in the table.

The problem that we run into here is that SQL Server can, like, find 37 million rows for this pretty easily. But finding the top 10 rows, right? Because we’re doing fetch next 10 rows only, offset zero rows, ordered by ID ascending.

It, you have to go through a lot of the table before you get to creation dates that meet this predicate. So, finding the top 10 ordered by this is what’s really tough. If we look at the execution plans for these, this first one takes 20 seconds.

Two, zero, 20, right? If we look at the clustered index scan, the number of rows that got read is this many, right? 5, 1, 4, 0, 1, 7, 1, 5.

That is an 8-digit number of rows. That’s a lot of rows. The number of rows in the table is 5, 2, 9, 2, 8, 7, 0, 0. That is also an 8-digit number of rows.

But if you notice, they both start with the same number, 5. And only once you get over to the second number, there’s only like maybe like a million and a half or so fewer rows that get read than there are rows in the table. And of course, since this happens awful in the single-threaded, and we have this top just like, gimme rows, gimme rows, gimme rows, gimme rows, gimme rows, that takes a whole long time, right?

It’s not a good thing. You can find stuff, you can find partially reasons for stuff like this in your query plans. If you look at the properties of an index access operator in a query plan that has like top or offset fetch, and you’ll see this thing in here, estimated rows without row goal, that’s going to be a sign that SQL Server said, well, you know, I think I have a different estimate in mind.

If we didn’t have that top 10 in there, I would have to read all of this. But with the top 10, I don’t have to read nearly as many. SQL Server is just like, you know, I think I can get away with a lot less than that, right?

So, fine there, right? All good. But then down here, notice that we do far less work, right? This thing spits out quite a large number of rows there.

This one spits out, oh, whoa, what just happened there? Developer PowerShell. That was a weird button. Let’s never hit that again. Let’s never touch that button again. Come on, there we go.

Zoom it. All right. So, for this one, we only had to read 18 rows to find anything that we cared about. So, that is, of course, far fewer, right? That is far fewer rows than you would want to deal with there.

Now, of course, Paul White, who is the most useful human being on the planet. Let’s just take a moment here to acknowledge that Paul White is the single most useful human being, maybe, that has ever existed. And you can’t spell Paul without the U for the most useful human.

We’ll workshop that later. Let’s just move on from that. That didn’t go so well. You can’t spell useful without Paul. Nah, screw it. Anyway, you can somewhat improve these queries.

And I’ll try to remember because, gosh darn it, I know how much you care to put this link, a tale of two index hints over at the much-loved SQL.Kiwi website in the video description. So, if you use a weird index hint and a tab lock hint, you can improve the performance of these queries quite dramatically.

These will drop down to about 1.3 seconds a piece. But now we have this sort in the query plan, right? Because SQL Server, when you use index zero in the tab lock hint, Paul explains this much better at his site.

But basically, like, you no longer do an ordered scan of this data, and then you have to sort this data. So, it does look a little bit funny that, like, we’re selecting from the table, and now all of a sudden we have to sort data to put it in order by the column of the primary clustered key that’s already in order by it.

So, that’s a little weird. But anyway, these do get slightly worse if we take out the tab lock hint, which I find quite amusing. And again, which if you go to the Paul’s post, you will find quite a bit of detail on this.

But these do go from 1.3 seconds a piece to almost 1.8 seconds a piece. So, that tab lock hint is, let’s just say, strictly necessary for the full performance benefits here. So, slight digression.

Anyway, let’s talk about why that equality sort range index does not help a query like this. So, this is my index v0, and I’ve got vote type id, id, and creation date. These are our equality sort range predicates, just like we talked about yesterday.

And both of these queries are hinted to find, to use that index. Now, this will help performance somewhat generally, right? Like, that first query, the first time we ran this using the clustered index, it took us 20 seconds to locate rows in there, right?

It was not a good time. We, you know, we beefed it on that one. We did not do well.

With that index, and with that index hinted, we save about five seconds. So, this is, again, not great, right? We did not, like, see the benefit from using that index methodology for this query the way that we do, the way that we did for the query yesterday.

And this is because, again, we need to seek through quite a number of rows. Even, like, we can seek to these rows now, and we can have this thing in order. But to evaluate this predicate on creation date, we still have to do a lot of extra work, right?

So, like, with that query in place, like, yesterday, this worked great. We did a seek. We had our data in order.

There’s no sort in this query plan or this query plan, I promise. But then applying this much narrower predicate on the creation date column completely screws things up, right? Like, we get the 37 million rows just by seeking to vote type ID 2.

But then after we find those 37 million rows, we have to go apply this predicate to all of them, right? It’s no fun, right? It’s no good at all.

So, the second query with ID in descending order does just fine with this, right? So, like, well, it’s not totally, this is, like, that funny intersection of, like, how indexes and queries work together. If your query demands rows in the ID with ascending order and your predicate is, like, something that’s way deep into the table, you’re going to have a bad time finding that data with this type of index.

The type of index that would work better if you need things in ascending order here would be an index like this that leads with creation date. And I’m going to show you two forms of this index. This one is creation date, then vote type ID, then ID.

The second one is going to be creation date ID, vote type ID. But the point for me, the point of me showing you both of those is that this sort of breaks the pattern that the equality sort range thing fixes. Because when you put the range stuff at the beginning of the index, even if there’s an equality predicate in the middle, like, it breaks that.

Because creation date is still the primary sorting and vote type ID is still only sorted after that. So, like, you don’t have the ID column in a useful order for this one. So, if we look at the query plans for this, these are both hinted to use the V1 index.

These will both be fast enough to find the rows that we care about. We do have a sort in the query plan, which, you know, was part of the thing that we wanted to get rid of with the ESR, the quality sort range index methodology, was having a sort in the plan. But in this case, we get the number of rows down into a pretty small batch.

So, the sort isn’t very painful in either of these. Both of these take just a little under 100 milliseconds. This is the second index in there that I promised I’d show you.

Creation date ID and then vote type ID. So, now we have, like, you know, range, sort, equality. But this doesn’t really make that much of a difference because, like, it’s just for, like, this specific query, you just do much better to be able to locate that narrow range and then look at vote type ID no matter where, almost no matter where it is in the index.

You can probably have it as an included column and it wouldn’t make any difference. So, if you run this is so, both of these will, both of these queries perform just about the same as with the index in slightly different order. So, like, swapping ID and vote type ID doesn’t make a big difference here.

One thing that you might want to consider is, like, just in general, like, the ordering of your columns and some columns, like, kind of share ordering. So, like, in this case, if you really wanted to get rid of the sort, you might consider ordering by creation date. In this case, for the votes table, the creation date column, like, like, obviously that’s for a new row that gets inserted.

When a new row gets inserted, the ID column, which is an identity, also increments. So, every creation date and every ID in this table is going to be higher than the one before it. You might have columns that similarly share ordering and that you might be able to rely on for this.

Now, just because of the way votes get inserted here, there aren’t going to be any duplicates for creation date. Right? Because, like, like, you’re just going to not have two things show up at the exact same time.

So, if you really wanted to get rid of the sort, you could run your query and instead order by creation date and just have a much simpler query plan overall. So, you might not always be able to get away with that, but in certain cases where you can, this might be a good thing to do. If you needed to have a tiebreaker in there, you would want to use this v2 index on creation date and then ID.

So, you could say, like, order by v.creation date, v.oops, ha ha, typing in demos. Look at this silly man go. So, if you needed the tiebreaker, like, this would be the better indexing strategy for these two, right?

Because you would have order by creation date, order by ID, and this index would be able to fully support these things. So, the equality sort range indexing, again, it’s great for a lot of situations, but for situations where your range is much narrower and sort of like, let’s just, like, to make it easy to physically sort of understand it. Like, the range is much narrower and towards the end of the table, and you’re ordering by stuff in ascending order.

Like, you have to read through a lot more of the table to get down to the stuff that you care about down here in order to find those rows. So, it’s not always going to work out perfectly for every query, but for some other, for some types of queries, it works amazingly as is. For other types of queries, you might have to either change your ordering to better, like, locate data towards the end of the table that you care about, or to sort by a different column in the table with the ES, with, like, you know, with some sort of index in place that helps you put this stuff in order without having to sort.

So, sort of a complex situation there, but one that is worth examining and one worth talking about. I do hope you enjoyed yourselves, and I hope you learned something, and with that out of the way, I don’t know, I’ll talk about some other fun stuff. Well, we’ll see what it is when we get there, though, won’t we?

Alright. 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.

Equality, Sort, Range Indexing In SQL Server – When It Works

Equality, Sort, Range Indexing In SQL Server – When It Works


Video Summary

In this video, I delve into a fascinating indexing methodology that I recently discovered and find incredibly useful for improving query performance in SQL Server databases. It’s not about creating new types of indexes but rather following an effective indexing strategy known as the Equality Sort Range (ESR) index. I explain how to structure your indexes by placing equality predicates first, followed by sorting elements, and ending with inequality predicates. This approach ensures that data is ordered efficiently for both seeking and ordering operations, leading to faster query execution times. Through practical examples, I demonstrate how this indexing method can significantly enhance performance compared to traditional index creation techniques.

Full Transcript

Erik Darling here. Your pal Erik Darling here with Darling Data. In today’s video, we’re going to discuss a term that I recently discovered, which is a wonderful way of phrasing an index methodology. Not a specific type of index, of course, not like a brand new style of index that you can create in your database, but just an indexing methodology that you can follow. generally used to improve query performance quite a bit. And that is the Equality Sort Range Index. It rolls right off the tongue, just like the POC index, the partition over covering index that is so very popular when people are talking about improving the performance of windowing functions. So we’re going to call this the ESR index. And we’re going to look at an example of how you can use this indexing methodology to improve your query performance. Yay!

We’re all excited. If you like this video content and you would like to be a supportive member of the audience, you can sign up for a membership using the link down below in the old video description. And you can, I don’t know, contribute to me being a happier, well, probably not healthier person, but you can contribute to me being a happier person that way. If you do not have a the dinero to contribute to that, to the happiness fund in that regard, you can always like comment and subscribe. And if you would like to ask questions of me privately that I will answer publicly, you can use that link, which is also in the video description. Coincidentally, many useful things down there to put your question into my magical Excel file that I will read from. If you need help with SQL Server, if you are struggling with performance, reliability, scalability, application, blah, blah, blah, blah, you can hire me as a consultant to do many useful things for you. Health checks, performance analysis, hands-on query and index tuning, all that other stuff that needs tuning, dealing with performance emergencies, and of course, training your developers so that performance emergencies are a thing of the past.

All worthy goals when it comes to SQL Server. If you would like some training, boy, do I have it. My pockets are full of it. You can get all about 24 hours worth of training from my pockets for 75% off. That’s the link, that’s the discount code. And like everything else useful in the world, the video description contains a fully assembled version for you to click on. Upcoming events, we have SQL Saturday, New York City, 2025. That’s this year. It’s hard to believe. Coming up May the 10th with a pre-con by Andreas Walter on May the 9th. And that’s about SQL Server performance monitoring and tuning and stuff. So we’re all looking forward to that. I’ll be there both days serving you lunch, bringing you, bringing you cookies and coffee and whatnot.

And so you can come hang out. Give me a hug. I don’t know, whatever you’re into. But with that out of the way, let’s party. Let’s do this thing. Let’s do this thing like we care about it. So I, for years, have been talking about this thing that I do when I’m tuning queries and indexes. But I had never, I always talked, it was always very clunky in my head. It was just like, but it’s like, you do the thing and then the other thing and then you care about this thing.

And then I saw a fellow named Frank Pachaud, I apologize, Frank, if I pronounce your name wrong, on LinkedIn talking, I guess he started a job with MongoDB recently. We’ll all forgive him for that. We’ll have a seance for Frank. We’ll talk to him in the database hell. I’m kidding. Where he posted a link to this thing in the MongoDB dots, where they talk about the equality sort range rule for indexing.

And I thought, wow, that’s a thing that I didn’t have a good name for. And so we are going to start referring to him. We’re going to meme this into existence for SQL Server, the ESR index, that is equality sort range. And we’re going to show some examples of that. Now, I’ve got a query down below and without any indexes, starting with no indexes on the POST table, SQL Server gives us a missing index request.

The missing index request that it gives us leads with POST type ID and then has last activity date as a second key column. And then in the includes, we have score and then view count. So the missing index request in SQL Server, as far as key columns go, are very WHERE clause centric.

If you look at the WHERE clause that we have here, we have WHERE POST type ID equals 4 and WHERE LAST activity date is greater than or equal to 2012-01-01. So SQL Server puts the equality predicate first and the inequality predicate second. And it doesn’t give a lot of thought to the fact that we are ordering by score over here, right?

Doesn’t really care about that. But we’re also selecting view count, right? So view count being in the includes, that’s fine.

But score being in the includes, that is not so fine. Because columns in the include of an index are not sorted or ordered in any useful way for, you know, either seeking to values or for helping with presentation or operator-dependent order buys. Like I’ve talked about in many other videos, things like merge joins and stream aggregates require sorted data.

And if you ask for data in an order that is not supported by an index, SQL Server has to put a sort operator into the query plan and break out its tiny little baby fingers and magically put your data in the presentation order that you have asked for. Other things like windowing functions also do pretty well with ordered data. So what we’re going to do is look at examples of these two queries using this index.

This is index P0. Both of these queries are hinted to use this index, mostly for a little bit of compactness here. We do have a few things to talk about.

And so I pre-created three or four indexes and I’ve hinted queries in each section to use those indexes so that there’s no weird overlap and oops, this query used this index this time. Sorry, whatever. So because that gets annoying.

So we’re going to run these two queries. And the first one is going to be pretty quick. And the second one is going to be a little bit less quick. And I’ll be honest with you, I am not fully used to SSMS 21 and where it puts the little grappling hooks for us to move things around on the screen with.

So you’ll have to bear with me while I acquaint myself with this wonderful 64-bit program. But for the first query, this is fast enough, right? This four milliseconds, six milliseconds total, great.

Like, no problem. Like, all easy peasy there. This one, not so great, right? We do an index seek. Okay, 284 milliseconds. But then we hit this sort and we spill a little bit.

Not so much that I’m, like, worried about it. And then we, of course, end up taking nearly a very devilish number of milliseconds to complete this query. So this isn’t really great.

This isn’t really an awesome scenario for the second query. But there is a way to make both of these fast. Now, a lot of people might be tempted to create an index that looks like this.

Where score is the leading key column. Because then we will always have score in descending order. The problem this presents us as query tuners is that with score is the leading column in the index.

It sort of acts as a gatekeeper to the other columns. So score is in order. But post type ID and last activity date are not in a useful order after this for searching.

So we sort of have this, like, blocker here that prevents us from seeking into the index for the values that we care about. So this is index P1. Both of these indexes, both of these queries are hinted to use index P1.

And if we run these, we’re going to get sort of not great performance out of either one. This query up above that took, well, like, a few milliseconds before is now what? Is that the right one?

Let me just go double check, make sure I didn’t mess anything up. No. All right. So, yeah. This one up here that used to be really fast took 1.5 seconds. This one down here, this one actually got a little bit better, right?

Even though we end up scanning this whole index, it got a little bit faster than last time. Mostly because we didn’t have the sort spill on this one, right? So this one did not take a devilish amount of time before.

This one just took a long time to find all the, scan through and find all the data that we care about. So what I’m going to show you now is the ESR style of index that I talked about in the video introduction.

We are going to lead with the equality predicate. We are going to follow that up with the sorting element in our query. And we are going to put the last activity date as the final key column. We’re still just going to include view count because view count, we don’t have a predicate.

We’re not in our where clauses, not in our order by. We’re not joining on it or anything. So there’s really not a lot of sense in there aside from just putting it in the included columns.

So let’s look at query performance with these two. And let’s see if this actually gets faster using our ESR index. And it does, right?

So this is about, this is what I want my query to look like. We have two very, very fast index seeks into our P2 index. This is our equality sort range index.

And we don’t need to sort data because the data is in order for us. Now, I just want to show you what the seek predicate looks like. This is going to be identical for both of these aside from the actual values in them.

This one’s four, this one’s 2012, the other one’s 2011 and one or something like that. But the important thing here is that we are able to seek in the index to where post type ID equals four.

And then we can take advantage of how B-trees store data, which is that like everything is primarily in this index ordered by post type ID. And then once we seek to any post type ID, like where post type ID equals something, all of the scores will be in descending order for that particular post type ID.

So we don’t, like, we’re not saying where post type ID is in four or five or greater than four, because that would mess things up because we would be crossing boundaries. We would be crossing post type ID boundaries to different post type IDs.

And the score column order would reset for each post type ID. So that wouldn’t do us any good. But for an equality predicate, where we just find all the rows for one thing, all of the data in the index is ordered within that one thing.

And that just gives us a quite opportune index to apply the C predicate, keep the data in order that we need for score, and then apply a residual predicate on last activity date to finish filtering out rows that don’t matter to us.

Right. And just because of the way indexes, B tree indexes work, we don’t even necessarily need view last activity date as a key column.

If for whatever reason you just wanted to have it as an included column, you would get the exact same execution plan. So just to show you what I mean, I’ve created a fourth index because we started our index numbering at zero because we’re nerds.

I put last activity date as a second include column here. Right. So it’s not even the first included column, but this is mostly just to get across the point that include column order doesn’t matter much.

If we run these two queries, we will get identical performance as the last query and our query plans will look just about exactly the same as well. Here is our index seek that goes directly to post type ID four.

And here is our residual predicate on the last activity date column. Now, the reason why this doesn’t matter so much here is because range predicate range or rather inequality predicates greater than greater than equal to less than less than equal to not equal to all that stuff is not no equality predicates and is no predicates are boom, you equal this.

like they often end up as residual predicates in queries anyway. Not all the time. Sometimes. Sometimes it happens. Sometimes it doesn’t.

Sometimes you have a seek and a residual predicate. But this is just to show you that the final key column in this case does not really have much impact on final query performance.

So when you’re looking at when you’re trying to tune queries that do something like this, they can, of course, be more complicated than this. But you can always get indexing for these to really help query performance when you embrace the equality sort range paradigm of index creation.

So you want to make sure if you have equality predicates, you want those to be the leading key or key columns in the index. You want your ordering elements to come after the equality predicates.

And you want any inequality predicates to come third in the index or come after the ordering elements in the index. Not necessarily third, of course.

Right? Could be tenth. I don’t know. At that point, you really start to see the benefit of included columns in indexes because you don’t have to have 13 key columns in order to support this sort of thing. So you could put your inequality predicates either as key columns after the sorting elements or in the includes because they will generally have less impact on things after that.

Now, there are always going to be some exceptions to the rule. If your inequality predicates are very, very selective, you might not want to have them as includes. If you’re seeking to like 10 billion rows and you have to apply a range predicate to like, you know, 9 billion rows afterwards, it’s maybe not as valuable.

But once you’re dealing with tables that large anyway, you should be using columnstore indexes. And I don’t know, I’m probably thinking about the meaning of deeper meanings in life because you might be a little, you might be dealing with many other things.

Also, you don’t see a lot of top 5,000 order by queries and that sort of situation. But anyway, thank you for watching. I hope you enjoyed yourselves.

I hope that you will embrace the equality sort range indexing methodology. I hope that you will join me in memeing this into widespread existence in SQL Server. And I will see you in another video where I will hopefully get back on track talking about store procedure stuff.

Really trying to work out some good demos for the temporary objects stuff that I want to talk about there. That might end up being more than one video because there’s a lot to say. But anyway, thank you for watching.

And I will see you in another video, I don’t know, shortly or longly or I’m really just not sure at this point. Well, the fates will decide. Anyway, 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.

SQL Server Books I Recommend

SQL Server Books I Recommend



Head on over to the books page!

Video Summary

In this video, I delve into my extensive collection of SQL Server books, sharing insights and recommendations based on years of experience in the field. From the foundational works like Ken Henderson’s “The Guru’s Guide to SQL Server Architecture” and “Gone But Not Forgotten,” which provide a deep dive into core concepts and are surprisingly relevant even today, to more recent titles such as Itzik Ben-Gan’s “T-SQL Fundamentals” and Louis Davidson’s “Pro-SQL Server Relational Database Design and Implementation,” I cover a wide range of topics that will benefit both beginners and seasoned professionals. Each book offers unique perspectives and practical knowledge, contributing incrementally to one’s understanding of SQL Server. Whether you’re looking for fundamental architecture insights or advanced troubleshooting techniques, there’s something in this collection for everyone.

Full Transcript

Erik Darling here with Darling Data. In today’s video, because I have gotten no fewer than like 10,000 questions on my office hours thing about SQL Server books or database books, we’re going to talk through my stack of books. And I have even put together a website, a page on my website that lists all of the books that I recommend. They are, of course, Amazon affiliate links because I spent 10 minutes putting together this list. And I figure over the span of time, the 53 cents that I’ll make from you people clicking these links and maybe buying things will be adequate compensation for my effort there. So let’s talk about books. The first one, and this is a granddaddy book. This is The Guru’s Guide to SQL Server Architecture and Architecture and Internals by Ken Henderson by Ken Henderson. This is by Ken Henderson, who’s dead. So RIP Ken. This one has a CD-ROM in it that is unopened, which I’m pretty psyched about. I did have to get a lot of these books second-hand. And I think one of my favorite things about buying second-hand books is the weird stuff that you find in them. I bought one sort of recently, unrelated to SQL Server, that had like a laminated, like kids-made bookmark, that said, like, Happy Father’s Day 2008. And my wife found it and she got kind of freaked out, but it was all explained. Anyway, this is a very good book. Old, but well worth it because you learn a lot from this stuff. This fills in a lot of fundamental knowledge stuff that a lot of people are missing.

We’re going to stick with Ken Henderson for a couple more here because Gone But Not Forgotten and certainly Not Gone Without Leaving is his mark on the world. We have the Guru’s Guide to Transact SQL, which covers many great and interesting T-SQL concepts and conventions. Granted, this is, again, old, but very useful. The one thing that is not in here, aside from a CD-ROM which is missing, is anything about API cursors, which I recently had some fun with and I will probably do a video about because, you know, that’s what I do. I have fun with things and I make videos about them for you. The third and final Ken Henderson book, which also has an unopened CD-ROM in it, is the Guru’s, well, sorry, there’s a sticker over there.

The Guru’s Guide to SQL Server, the Guru’s Guide to SQL Server, Store Procedures, XML and HTML. Granted, I would probably not recommend doing much HTML with SQL Server, but XML still around to this day. This of course predates JSON, so we can’t really go into detail on that. But everything else in there is absolutely wonderful. Moving on now from the Ken Henderson wing of my library into the, well, actually, no. This is, this is, there’s one more from Ken Henderson before we move on to other ones. SQL Server 2005 Practical Troubleshooting.

Well, sorry, this is edited by Ken Henderson. Who is the author on this? This might have like 17 authors. I don’t know. Let’s see. Let’s open this up. Edited by Ken Henderson. Let’s see what we got here. We got a table of contents. This is going to go on for a while. About the authors. All right. Okay, cool. Well, let me, there are, there are a number of notable people in here. Some of them I haven’t heard of, but we have August Hill.

We have Cesar Galindo Ligari, who is still on the SQL Server Optimizer team. Very smart fella. Ken Henderson, of course. Samir Tajani. Santeri. Oh boy. Vudelenin. Slava Ox. Hey, my pal Slava Ox. Wee Zhao. Bart Duncan. Great SQL Server blogger from back in the day. And of course, Bob Ward from back when he was in, it’s going to be hard for me to show you this, but actually, yeah, that’s not working out well at all.

But this is Bob Ward when he was still in Microsoft Customer Support Services. And Cindy Gross is the final one noted here. So that, that, this is a collection of authors. So edited by Ken Henderson. Sort of a slightly weird thing there. Anyway, now we’re going to move on to the Kaylin Delaney et al. wing of my library. We’re going to start off with Inside SQL Server 2005 Query Tuning and Optimization. Now I know what you’re going to say. Query tuning in 2005 is totally different than it was today. It’s not. A lot of the same stuff still applies. We just have some new tools and some new techniques, but there is a lot of fantastic information in here for folks who need to learn fundamentals and who need to maybe see just how similar and just how consistent the concepts in database query tuning and optimization are.

This one is maybe not so important to query tuning, but it is, it is a cool book. This is Microsoft Inside the Storage Engine for SQL Server 2005. Now I know that the storage engine has had many changes and many things added to it and stuff like that, but there is still a lot of very good foundational knowledge in this book. Next up, we have Microsoft SQL Server 2008 internals. Internals knowledge, very good stuff to have. Even in 2008, there’s good stuff to learn in here. One thing that you’re going to find across all of these books is that you’re going to pick up something new in all of them, right? I don’t mean new in like, oh, this is like, like, obviously we’re up to SQL Server 2022. There have been whispers of SQL Server 2025 already. But one thing that you’re going to get across all of these is incremental. There’s going to be some stuff in some books that you might not see in the other books.

There’s going to be some of these books that you might not see in the other books. And there’s going to be a knowledge accumulation for you as you go across your learning journey. And then this is probably the last of the great SQL Server internals books, SQL Server 2012 internals. So the 2008 book was, had contributors, Paul S. Randall, Kimberly L. Tripp, Connor Cunningham, Adam Mechanic. All right, a lot of good stuff there.

And this one here, we have, we still have Connor Cunningham. We got John Cahias. We got Paul Randall. We got Bob Beauchemin. We got all sorts of smart people contributing to these books. Now, we’re going to move on to the Itzik Ben-Gan wing of my library.

And we are going to see T-SQL Fundamentals. This is the fourth edition. Itzik, before he went into semi-retired hermit phase, did update this. This is the latest edition of that. Continuing on with the Itzik wing of my library, we have T-SQL Querying.

Thick book, good book. I’ve had this one since, oh, it came out in about 20, what was it, 2015, I think, 20, somewhere there. This one is Itzik, Dajan Sarka, Smartfella, Adam Mechanic, Kevin Farley. Kevin Farley, who recently retired from Microsoft. Good for him.

Next up, a slightly more recent book. We have Pro-SQL Server Relational Database Design and Implementation by Louis Davidson. Louis was kind enough to have me on the Redgate Simple Talks podcast recently.

If you haven’t listened to that podcast generally, or at least my episode, I can highly recommend you go do that. And the final book that I have here is by a fella named Dimitri Karatkevich, SQL Server Advanced Troubleshooting and Performance Tuning. I do like this book quite a bit. There was actually even something in here that he discussed.

I forget exactly what it was at this point. There was something with the DMV query that I thought was cool. I actually realized that I didn’t have that in SP pressure detector, so I added it in. I think I even have his name in the pull request for it, but I forget a little bit.

But anyway, this is a very good book. And I think one of the things that I liked best about this book is, you know, a lot of the times that I’m reading something, I have, like, the stuff that I would think and say when I’m talking about something.

And, like, he would be, like, talking about a topic, and it would, like, you know, like, he’d, like, you know, make a point about something. And then I’d be like, yeah, but, like, this other thing that you have to take into account with it. And then the next sentence would be like, but of course you must consider.

And I was like, yes, this is a very good book. So if you are a bookish person, those are the 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 books about SQL Server that I generally recommend. There are a couple notable books that are not on this list because they are not about SQL Server specifically that are also good.

They are Database Reliability Engineering and Designing Data Intensive Applications. But you can get all of, you can get the full list with Amazon links to purchase these books on my website. That’s going to be erikdarling.com slash books.

I will have the link to my site in the video description here. And you can go buy them and you can go learn from them. And maybe, since you’re most likely buying used books, maybe you can find some cool artifacts from the sands of time in there.

But anyway, thank you for watching. I hope you enjoyed yourselves. I hope you learned something.

And I hope that you will go buy some books if that is your preferred vehicle for learning about things. So 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.

The Weird World Of SQL Server API Cursors #tsql2sday

The Weird World Of SQL Server API Cursors #tsql2sday



Thanks for watching!

Video Summary

In this video, I delve into the fascinating yet somewhat obscure topic of API cursors in SQL Server, exploring their unique capabilities and usage scenarios that go beyond the typical row-by-row processing. While most people might cringe at the mention of cursors due to common misconceptions or past frustrations, I aim to demystify these powerful tools by walking you through a practical example where we use an API cursor to batch update multiple rows efficiently. This approach not only showcases the flexibility and power of SQL Server but also highlights the importance of understanding its less commonly known features for advanced database management tasks.

Full Transcript

Erik Darling here with Darling Data. In today’s video, we’re going to get into the weird, wild world of API cursors. Now, this is something that most people who use SQL Server have never heard of and probably have never used. If you’re the type of person who just has the standard Pavlovian response, seeing a cursor declared or used anywhere and complains and gripes about it, this is not the video for you. I don’t like you much. So there’s that. We’re going to talk today about how API cursors can be used in ways to traverse more than just a row at a time. This is not a row by agonizing row thing. We can actually process, select, select, modify multiple rows at a time using API cursors, but we’re going to have to do a little, we’re going to have to do a little bit of digging into the vaults to, to understand what’s going on here. So with that out of the way, if you like this content and you would like to support my efforts to bring you high quality SQL Server content like this, you can sign up for a channel membership link right there.

down in the video description. If you are too poor because you spent all your money griping about cursors in SQL Server to some LLM trying to get it to write a blog post for you. Well, there are the ways to support the channel. You can like, you can comment, you can subscribe, and you can ask me questions privately that I will answer publicly during my office hours episodes. If you need help with SQL Server, performance help with SQL Server, I can do all this stuff. And of course, as mentioned is rated by beer gut magazine to be the best SQL Server consultant in the world outside of New Zealand. Today’s video will of course, help establish why outside of New Zealand is particularly important to that distinction. If you would like to get some very high quality, very low cost SQL Server training content, you can get all 24 hours of mine for about 150 US dollars. And you get that for life. There is no return fee on that. The link is up there. The discount code is there, of course, all fully assembled for you down in the video description.

Of course, if you would like to hang out in person. And I don’t know, high five, take selfies, sign autographs. I don’t know, ask me how to set Mac stop. You can of course come to SQL Saturday New York City 2025 taking place on May the 10th in lovely Times Square Manhattan at the Microsoft offices. I believe it’s 11 Times Square. If you go to my website, there’s a link up in the corner. All that stuff. Go there. If you go there. If you go there. If you go there. If you don’t know what my website is, well, geez, that’s a scary thought. It’s a scary thought. Anyway, let’s talk about API cursors. So before I show you my thing, what I want to show you is where I learned about API cursors from and sort of like why I got interested in them. Because I think they’re just bizarrely interesting things. So Paul White from New Zealand has a couple blog posts or not a couple blog posts, has a couple Q&As on the database administrator stack exchange site. Now, I want you to pay careful attention. I’m not logged in up here, right? There is a login prompt. So I don’t want you to think that like I haven’t, I haven’t upvoted these questions because when I’m logged in, you absolutely will see.

That these things have been upvoted to the nth degree. I will put the links to these questions in the video description, hopefully, if I remember. We’ll see. But anyway, if we scroll down here to the answer, we will get to what Paul said. And of course, this is exactly the behavior of an appropriately configured API cursor. Now, if you look at this code, it is some of the most outlandish stuff I have ever seen written. Right? We have some things declared and set using these horizontal lines, some sort of XOR, bitwise, something or other to make numbers out of multiple numbers that make sense to API cursors.

And then there are some stored procedures like SP cursor open, SP cursor option and SP cursor fetch. And I believe it’s not this one. There’s also an SP cursor close. So this is where I first saw anything about API cursors. Now, if you work with SQL Server. And you work with like a vendor product and you see lots of queries running like fetch API something, something, something, something. They are using API cursors, but they are probably not using correctly configured API cursors. They are probably using just whatever stock crap they came up with. As we’ll see in a moment, the Microsoft documentation on API cursors is not good.

This is the other answer I saw where Paul brought up API cursors. I don’t think there are any others on Stack Exchange. There are probably some elsewhere in the world. But a favorite. Look at that. Look at that delicate U in there. Favorite solution of mine is to use an API cursor. I didn’t mention anything about it being correctly configured in this case, but we can assume because it’s Paul, it is correctly configured.

But it uses sort of the same set of stored procedures there. And there is this absolutely wild thing. Well, cursor status global my cursor name equals one. Keep going and finding things. So if you want some background and you want to see some API cursor code, the links to these will be in the video description.

Now, the Microsoft documentation on API cursors is incredibly sparse. Like you’ll get some like you’ll get like valid stuff in here, but there’s really no mention of like correctly configuring them. Like you get a lot of information about cursor stuff, which like if you understand cursors generally would make makes more sense to you.

But if you don’t understand cursors generally and you are the type of person who just, again, has the dog whistle response to like, oh, cursors. Oh, there’s very little hope for you anyway. There’s SP cursor. So we just looked at cursor open.

This is SP cursor, which has sort of the same set of stuff in there. And then we have SP cursor fetch, which does a whole bunch of other stuff. There are other SP cursor procedures in the mix, of course.

There are all sorts of weird things you can do with cursors that you probably didn’t know you could do. So there’s a wide world out there. Now, what I wanted to show you is the thing that I wanted to do.

Now, this is in no way supposed to besmirch the wonderful Michael J. Swart post about batching modifications. This is just an alternate approach to batching modifications. Not to say that you need to do this when you batch modifications, but you might be able to have some fun with it at some point in your life.

So I’m going to walk through the code and then I’m going to run the code. And I’m going to point out exactly where I got a little assistance with the code because things were kind of annoying. So I am creating a table of sample data.

That much should be very obvious. I’m going to put 10,000 rows into the sample data. And in those 10,000 rows, I’m going to mark 5,000 of them as needing an update. Right.

So case when this number, the module is 2 equals 0, then 1. So out of the 10,000 rows, like 5,000 of them will have the needs update set to 1 based on this row number. All right.

After that finishes, I’m going to show you the 5,000 rows that need an update. And then we are going to get into the cursor stuff. Now, the goal of this cursor is to update 1,000 rows at a time.

Right. And we’re going to handle that with some of these fancy parameters in here. Now, this is, again, not for the faint of heart.

This is a very difficult to follow set of things. There are a lot of things to declare and keep track of. But here is our query that runs when the cursor runs.

We are also going to declare this dummy table. And the purpose of this dummy table is to eat results. So usually on every time, on every execution of these cursor procedures, SQL Server returns a result set from the cursor.

I don’t want to see that because I want, like, rather, I didn’t want to see that because I was like, you know, like, they just clog up the screen. It looks silly. It makes me, you know, gives me the face vibrations I don’t like.

And so Paul suggested doing the insert top zero into dummy when executing the procedure. All right. So if that looks just stunningly out of this world, insane to you, that’s what that’s doing.

That’s the purpose of that. On each trip through the cursor, I’m going to select a row count so you can see that a thousand rows come out of a thing. I’m going to put this on GitHub.

I usually don’t, but this is so weird that, you know, screw it. I’m going to put it out there. And so this is what does the update in here. And this is so bizarre.

This is so weird. All right. I have to tell it which table to update, which I guess technically I can put an empty string in here because there’s only one table, but whatever. And then here’s what I’m doing.

I’m setting the price times 1.10. I’m setting last updated to sysdate time. And I am setting needs update to zero. Okay.

So then I’m going to show you via the row count big function that how many rows I do at a time. We’re going to fetch the next batch and we’re going to do all this stuff. And then at the very end, I am going to show you, I’m going to verify that the updates ran.

So if you are all ready to see this happen, let’s run this. And let’s admire these results for a moment. So these are the 5,000 rows that need an update.

All right. You’ll see that this, like just looking at the top, like I guess there’s eight visible rows here. We have two, four, six, eight, 10, 12, 14, 16.

We’re pretty much counting by twos. Right. These are all the ones that needed an update. Here’s the original price. The original quantity. I didn’t change quantity, of course, just price.

And then down here, you’ll see that these numbers did go up or rather these numbers did change. Right. So this is the last query that shows the data that I just messed with. Product two, four, six, eight, 10, 12, 16.

The prices are all 1.10 higher. And the last updated has been incremented to today. And the needs update is now set to zero. So these went from 2024, 630 to 2024, 317.

So this did work. And if you look at the five calls to row count in here, there’s 1,000, 2,000, 3,000, 4,000, 5,000. So I updated these 5,000 rows, 1,000 rows at a time.

And I did that using an API cursor. This type of syntax is not available. Rather, this type of behavior is not available using a stock and standard cursor.

You do have to get into the weird world of API cursors and do stuff like this. So when do you use these? These?

Probably when you have gotten to the point where you cannot be satisfied by normal queries. I get a thick callus for stuff in SQL Server these days. And this was a nice way to sand that callus down and feel things again.

So, you know, of course, thank you to Paul for the assistance with some of the coding here. And, of course, for publishing the original answers that opened up my world and mind to API cursors. And, yeah, I hope that this will encourage you to keep learning about things in SQL Server because there are all sorts of interesting things you can do once you peel the world back a little bit.

Anyway, thank you for watching. I hope you learned something. I mean, I’m pretty sure you learned something. I hope you enjoyed yourselves.

And, again, the links to the code and to the original DBA stack exchange questions so you can read more about API cursor stuff will be in the video description. But, again, this is a weird one. I admit it.

I fully and totally admit this was a weird video. But it was something that I was rather proud to show off because most of the stuff that I do is pretty much like, you’re going to see this every day and it’s going to be a problem.

This is nice and weird. Anyway, I’m out of here. I’m going to go un-weird myself a little. Goodbye.

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.

SQL Server Performance Office Hours Episode 7

SQL Server Performance Office Hours Episode 7


How do I size SQL Server for new project? Where to start, what to take into account? THX!
When are you going to start adding your referenced links to the details section so i can copy and paste? <3
Should one still care about Index Fragmentation in the days of Azure VM Premium disks, or local SSD’s
When (if ever) will we see a Tyson vs Paul type grudge match between Erik and Brent
your face looks smaller lately. r u sick?

To ask your questions, head over here.

Video Summary

In this video, I address several questions from viewers. First, I tackle the topic of index fragmentation in modern storage solutions like Azure VM premium disks and local SSDs, explaining that while logical fragmentation is less of a concern, physical fragmentation can still impact performance but isn’t typically measured by standard scripts. Additionally, I discuss my recent weight loss journey, attributing it to a combination of reduced gym attendance due to the pandemic and aging, which has made maintaining high strength levels more challenging. The video also includes some light-hearted questions about potential future collaborations with other industry experts and a bit of self-deprecating humor regarding my appearance.

Full Transcript

Erik Darling here with Darling Data and boy howdy we’re gonna do it. We’re gonna drop in office hours here. Where I answer five of your questions at a time that you submit to me through my form. If you want to ask a question here you can do that at this link. This link is available in the video description down below. While you’re looking at the video description down below, if you think, boy, this Erik Darling sure does produce a lot of content that I rather enjoy. Maybe I don’t always learn something. Maybe I do. Maybe I don’t always enjoy myself. Maybe I do. But I would like to support those efforts. You can, you can, while you’re, while you’re floating around down there, there’s, you can, you can become a subscribing member of the channel. And for as little as, as little as $4 a month, you can, I don’t know. What, what is, what is $4 a month? At the end of the day. It’s really what it, what it does in the aggregate, right? About 60 other people have decided to be so kind as to support my efforts here. So, uh, you would, you would join the, that choir of angels.

And I would, I would be eternally grateful to you in the aggregate. Uh, if you, if you ran out of $4 a month, and maybe you died, uh, you can, you can, from the grave, you know, this is America. So, if you can, dead people vote. So, if you, dead people want to like, comment, and subscribe, you can, uh, you can, of course, do that as an alternate means of supporting the channel, uh, from this mortal coil or, uh, from, from, from beyond. If, uh, dead or alive, you would like help with your SQL Server, uh, I am, I am very good at all of these things. Uh, some, some, by some, I mean the, the nice folks at Beargut Magazine might say that I am, I am the best in three out of four hemispheres of the world at it.

Uh, if there weren’t for that damn island nation in the, in the Pacific, I would, I would reign supreme over the entire globe. And if you need a health check, some performance analysis, some hands-on tuning, uh, if you are having a performance emergency, or if you want to get your developers training so that, uh, your SQL Server stops being consistently on fire, well, you can call me up and I’ll do that. And as always, my rates are reasonable.

Uh, if you would like some reasonably priced SQL Server performance tuning training, I have that as well. About 24 hours of it. Uh, available at that URL with that, with that coupon code, which is also fully assembled for you down in the video description.

So, there’s a lot, there’s a lot you can do with the video description that will, that will clarify many things in your life for you. Uh, SQL Saturday, New York City. Come in your, come in your handy dandy way, your happy way, uh, on May the 10th.

That is this May the 10th of 2025, taking place at the Microsoft offices in Times Square. Highly suggest you, uh, find that event and buy a ticket because, uh, space is limited and those tickets are going, what, faster than Sbarro pizza slices. So, that out of the way, uh, let’s, let’s do this office hours thing.

Got, got quite a lineup of questions here. Uh, first and foremost, uh, we have this question. How do I size SQL Server for new project?

Where to start? What to take into account? Fix. Well, uh, there’s a lot of stuff to collect on this, right? Um, new project.

Wow. A lot of stakeholders involved. Um, uh, you know, some, something that might help is if, uh, this is, uh, a new project. That, uh, is using an existing third-party piece of software.

Third parties will often publish some sort of minimum specs for, uh, what, what they expect out of a SQL Server. Uh, this would include hardware, version edition, all that good stuff. Um, and, uh, you, if, if this is a, for a third-party piece of software, you might, you might even ask them, uh, what the typical, what the average installation is.

Um, is for a SQL Server, at least, at least as far as database size goes. They might, they might have some ideas there that would help you out. Um, but if I, uh, you know, other things that you might want to take into account is talking to various stakeholders about the importance of this project.

Um, you know, it might, it might be something where, uh, you know, high availability and disaster recovery are a must off the bat. It might also be a thing where they’re like, let’s just, let’s just build an MVP and see how it goes. Uh, a lot of the times, um, you know, when these projects start off, uh, they are on, uh, you know, the, the database has no data in it.

So, if you’ve got that going for you, it doesn’t, almost doesn’t matter what, what size SQL Server you start with, uh, especially given the flexibility of hardware configurations, both with virtual machines and the cloud these days. Um, uh, I had another thing to say there. Um, if this is, uh, you know, a new project that is perhaps based off an existing project, you might take a look at the, the current set of things there.

Uh, like, you know, whatever, whatever hardware is in the current SQL Server and all that. Um, look, there’s, there’s not, there’s not a whole lot here for me to go on. So I could just keep listing off different things that you, you might think about and ask as you’re doing this.

But, uh, really, um, this is the sort of thing where that, you know, DBAs do, do have to get paid for because sizing a SQL Server is not just a one-time set it and forget it thing. You need to, you need to keep an eye on the performance of this SQL Server if this is something that you care enough about to, to ask the question. Uh, I would say that, uh, you know, you want to keep an eye on those weight stats and make sure that your hardware is keeping, whatever hardware you initially assigned to, that is keeping up with the workload, the number of users, all the queries that are in there.

Um, you know, if it’s a, if it’s an in-house project and people keep adding features and stuff, you’re going to have to keep looking at indexes and other aspects of the database to make sure that it stays in touch with development reality. So, uh, I don’t know, like, I think maybe, maybe it depends a little bit on, uh, how much people are willing to spend on it at first. Uh, you know, if it’s, if it’s going into, it’s going into the cloud, uh, whether it’s on a VM or on a platform as a service offering from any cloud vendor, you might want to ask what people are willing to spend on it because that’ll do a pretty good job of dictating, uh, exactly how much hardware you can get out of it.

Uh, if it’s, if it’s going to be an on-prem virtual machine or something, uh, then it has a little bit less effect. But, uh, you know, you might start, you might think about like, um, you know, for standard edition, right? And I’m not, I’m not saying that you would ever use standard edition.

I’m not calling you that much of a cheapskate. But what I am saying is that for a lot of people, when they build a standard edition box, uh, like VM somewhere, uh, they will, uh, choose a set of hardware. Uh, that maximizes the capability of SQL Server standard edition, uh, you know, somewhere between eight and 24 cores, depending on, uh, the workload that hits it.

Uh, 192 gigs of memory because SQL Server standard edition, uh, well, it is capped at 24 CPUs these days. And at least as far as I’m aware, SQL Server 2025 has not changed any of the capacity limits for SQL Server standard edition. So you still have the 128 gig cap on the buffer pool, but what you, but, uh, what, what a very common practice with standard edition is, is to give the SQL Server, uh, about 192 or so gigs of memory.

Set max server memory somewhere in the 180s. And that way you have 128 gigs of data, of memory rather for the buffer pool. And then SQL Server is allowed to use memory between the end of the buffer pool and max server memory for all sorts of other things.

So it might be smart enough to just start all your builds with a maxed out standard edition build, even if you’re using enterprise edition. That’s, um, usually an okay way to go. Of course, uh, CPU count has a much bigger impact with enterprise edition than with standard edition.

Um, it being the, the, the $2,000 of a core versus $7,000 of course. So again, it really does come back to budgetary constraints and what people are willing to spend on this hardware. Doesn’t it?

So make sure you get those numbers, right? Second question here is, when are you going to start adding, oh, that was the wrong button. When are you, when is zoom it going to start listening to me?

Uh, when are you going to start adding your reference links to the detail section so I can copy and paste? Well, uh, I, I, I always endeavor to include all of the, the reference links in my, in my video descriptions. If I ever miss them, please feel free to point it out.

Uh, and I will correct, I will aim to be as eventually correct as MongoDB and, and, and, and get that in there for you. But, um, I am, I am an imperfect soul and all I can do is beg for your forgiveness and, and, and, and try to correct any, any issues in that area. And let’s see here.

Should one still care about index fragmentation in the days of Azure VM premium disks or local SSD, SSDs? What? Apostrophe abuse right off the bat.

Uh, no. So look, this is something that I’ve, I’ve, I’ve talked about a bit. Uh, the type of index fragmentation that most people, uh, cared about at some point in time was logical fragmentation. It’s data pages being out of order, uh, on, on, on disk.

And that is, no, that is not something that I tend to care much about when it comes to, um, when it comes to SSDs or flash or, or, or memory or like, you know, RAM memory, uh, not RAM disks. That’s not for SQL Server. Uh, but, uh, there, there is always a specter of physical fragmentation that is empty space on data pages.

Um, and that can affect scan density. That can affect read ahead, read size. And, you know, it might be something that you want to look at.

The problem is that, um, not, not many, uh, readily available, uh, index maintenance scripts measure physical fragmentation. They all measure logical fragmentation. And there’s not really a good correlation between a logically fragmented index and a physically fragmented index in either direction.

Uh, if you want to go and start measuring, uh, uh, physical fragmentation. And you want to start, uh, rebuilding or reorganizing indexes or in order to, uh, cram your data pages more densely, uh, with data. Then you are, you are welcome to figure out at what threshold that makes sense for you to do and, uh, and pursue that endeavor.

But, um, if you are, if you are just asking me, like, how to configure all the scripts or something or something like that, it’s not in there. So, um, that is something that you have to kind of figure out a bit on your own. And it’s not something that, that I want to get into the business of doing because there are all sorts of situations out there where, uh, even physical fragmentation would have no profound effect on a workload.

If the queries are, if the majority of the queries are performing index, index seeks, it is index scans that are affected by the page density that is lessened by physical fragmentation. And seeks don’t really have that sort of performance hit. So, uh, this is a weird question.

When, if ever, will we see, no, zoom it, listen to me. When, if ever, will we see a Tyson versus Paul type grudge match between Eric and Brent? It’s a, it’s a very strange question.

Um, I wasn’t aware of a grudge between myself and Brent. Uh, if there is one perhaps that I’m unaware of, uh, you can feel free to, uh, enlighten me about that. Uh, at least the last, last time I spoke to him, uh, fairly recently, there was, there was still no, there was no grudge.

So, uh, the, the, the, the, um, potential for a grudge match does infer the existence of a grudge. But, um, at least I am unaware of one. And finally, your face looks smaller lately.

Are you sick? Well, thanks for noticing. I do appreciate it. Uh, a fella does work hard to, to keep in shape. Uh, no, I, I’m, I’m, I’m not sick.

I am, I am, I am as well as I’ve ever been. Uh, I did, I did lose some weight though. Uh, if you, if you want, if you, if you, if you care about a full, uh, the full story, uh, you can, you can keep listening. If you, if you don’t care for, uh, any sort of explanation, uh, you can, you can stop watching the video now.

But, uh, around about, uh, 2016, I got very much into, uh, strength training and like sort of a, like a powerlifting type thing. And, uh, you know, before that, I, I just kind of horsed around in the gym like many misled, uh, time-wasting young gentlemen. And, uh, I just realized, after a while, I was just like, this isn’t really getting me where I wanted.

So, um, I, I, I discovered the, uh, the starting strength program by, by Mark Ribiteau. And I started doing, uh, the novice linear progression. And, uh, after, after a few years, uh, I got, I got my lifts up pretty good.

But I, I was also, uh, you know, that, that getting stronger does require putting on body weight. Generally, if you want to gain muscle, you’re bound to gain some fat in there. But, uh, you know, I, I, I bulked up to about 225, 220 in there.

And, uh, you know, my lifts were my, but I had like lifts to match that. You know, I was dead lifting around 600. I was squatting over 500.

Um, I was benching over 300. I had a 250 something pound overhead press. And these are all for like singles. This wasn’t like me just banging out reps with that stuff. But I did get my lifts up pretty high.

And, uh, but, you know, I felt kind of okay about it because that’s the goal I was pursuing at the time. And the additional body mass was, uh, was sort of required for me to pursue that goal. But then, you know, um, COVID came around and, uh, in New York, gyms closed down for quite a while.

And then when they reopened, uh, you still had to wear a mask in the gym, which I, which I did try to do a couple of few times, but for the type of lifting that I was doing, it was very uncomfortable.

So, um, you know, I, I did, I did drop my weight back down a little bit and, uh, then I lost about 20, 25 pounds, uh, because I just wasn’t working out and, you know, carrying all that around when you’re not actively lifting heavy weights is kind of, but then I could just never, um, you know, uh, I got older, my, my, my, my mid middish forties.

And, uh, I could just never get, um, the type of training going where, uh, I was, I was getting my lifts back up to that. Right.

After take, after that long of a layoff in the gym, it’s like, you’re starting basically from scratch. And so, uh, yeah, you know, I just, I just kind of realized that, uh, is a, is a, is an aging gentleman and, uh, you know, uh, sort of struggling a bit with training consistency and stuff like that, that I just wasn’t going to get my, my lifts back up to where they were.

So, uh, I just, you know, decided, you know, lifts be damned. Unfortunately, uh, I, I, I did, uh, pursue just losing weight. I was still, still, still lifting weights, but all of my, the, like my, my lifts for what they were just dropped way down.

Uh, now, um, you know, just sort of, uh, slowly trying to add back some, some strength into the mix and, uh, get them at least back to some respectable numbers. But, you know, that’s going to be a slow process because, uh, I am not, uh, I am not in the same, uh, bulking frame of mind that I was the first time around.

So, you know, it’s, you get a bit stronger, but also not, you know, bulk up to some horrible weight. I am at the, I’m at the point of my life where doctors are starting to prescribe interventions for certain things like blood pressure, cholesterol, and all that other stuff they give you because you’re going to die if you don’t take it or something.

So, uh, uh, I’m not sick, but, um, I was, I was feeling not so great there for a bit. Uh, cause, you know, I had, I had all of the, uh, the, the outer symptoms of, uh, of, of a powerlifting career without any of the, the, the strength that went along with it, which is not a, not a terribly good combination.

Uh, so, that’s my story there. If you listened, thank you. If you didn’t, I totally understand. Anyway, uh, that does bring us to the end of this office hours. Uh, again, you can submit your questions, uh, via the, the link down in the video description that says office hours, and I will happily answer them.

So, uh, thank you for watching. I hope you enjoyed yourselves. I hope you learned something. And I hope that you, uh, if you are a young, young person wasting your time in the gym, you will stop doing that.

Get some, some barbells in your life. It’s a much better way to live. Anyway, thank you for watching. Goodbye.

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.