Brent Ozar Unlimited®: Recent Episodes

None

SQL Server training, tools, and free downloads.

View Details

Common Table Expressions are awesome because they let SQL Server reorder processing in whatever way it deems to be the most efficient for your current data distribution, on your current version of SQL Server. Default to CTEs.

When SQL Server gets that process wrong, switch to temp tables.

Let’s start with an example. I’m using SQL Server 2025 and the big Stack Overflow 2024-04 database in 2025 compat level.

The below query says, “Find the most popular Users.Location – the one with the most people in it – and then amongst the people who live there, find the top 250 users with the highest Reputation score.” It also creates a couple of indexes to help.

CREATE INDEX Location ON dbo.Users(Location);CREATE INDEX Reputation ON dbo.Users(Reputation);GOSET STATISTICS IO ON;WITH TopLocation AS (SELECT TOP 1 Location FROM dbo.Users WHERE Location <> '' GROUP BY Location ORDER BY COUNT(*) DESC)SELECT TOP 250 u.* FROM TopLocation tl INNER JOIN dbo.Users u ON tl.Location = u.Location ORDER BY u.Reputation DESC; Does that query produce a good plan? Well, one of the ways we judge it is to look at its logical reads – in this case, we read 478,982 pages:

Is that a lot? Well, for comparison, here’s the size of the whole table:

That means in order to execute this query, SQL Server read more pages than there are in the entire clustered index of the table – despite the fact that we have indexes to help. If we look at the actual execution plan of the CTE query, we can see that SQL Server did indeed use the indexes:

Like I tell students in my Fundamentals of Query Tuning class, if there’s only one thing you take away from the entire class, let it be this: when you’re unhappy with a query’s performance, read the plan from right to left, top to bottom, looking for the first place where estimates versus actuals are 10x off or more.

In our example, as we read from right to left, the first thing that’s happening is the CTE. SQL Server is diving into the first non-null, non-empty-space Location in the Location index, aggregating them together to get counts of the number of people who live in each one, and then sorting them by that population count. At the time this sort finishes, SQL Server knows that it’s going to find 1 location – so far, so good, our estimates have been bang on:

So far, so good, our estimates have been bang on.

The next thing that happens is SQL Server dives into the Location index to find the people who live in that top 1 location. “Hey, SQL Server, how many rows do you think you’re gonna find?”

“FOURTEEN, BAWSS.”

“Uh, SQL Server, how many rows did you actually find for that location?”

“UH… MORE THAN FOURTEEN, BAWSS. SORRY, BAWSS.”

So as a result, it ends up doing 113,399 key lookups to get each user’s reputation. Each of those key lookups results in a few logical reads, and 113,399 * 3 reads each = big data reads, relatively speaking.

The problem: SQL Server knows we’re looking for just 1 location, but it doesn’t know what that location is, and what shocks most people the mostest, it doesn’t really put together the fact that we’re looking for the most-popular location. It thinks we’re looking for the average location. We need a way to help SQL Server to understand that the one location value we’re looking for is something special.

Back to our opening paragraph, I said start with a CTE – and if that isn’t getting the performance results you want, try substituting the CTE with a temp table:

DROP TABLE IF EXISTS #TopLocation;CREATE TABLE #TopLocation (Location NVARCHAR(200));INSERT INTO #TopLocation (Location) SELECT TOP 1 Location FROM dbo.Users WHERE Location <> '' GROUP BY Location ORDER BY COUNT(*) DESC;SELECT TOP 250 u.* FROM #TopLocation tl INNER JOIN dbo.Users u ON tl.Location = u.Location ORDER BY u.Reputation DESC; Check the logical reads:

They’re down by 2/3! Let’s look at the execution plan to see what changed:

The first query is populating the temp table, same work as the CTE. That part was never the problem for logical reads, and the estimates were always great.

The second query is where things get spicy. SQL Server chose to scan the Reputation index backwards, from highest reputation to lowest, and for each person it found, it did a key lookup to check whether that person lives in our particular chosen location or not.

That sounds bizarre, but for locations that show up very often, this turns out to be very efficient! Note that the plan also doesn’t require a sort – the data’s already sorted by reputation descending – so there’s no sort in the plan, only a Top, which is like a cutoff valve that drops when we meet our 250 row goal.

In that second query plan, read the estimates vs actuals from right to left, top to bottom, and they’re muuuuuch closer than our CTE query was.

In this case, the temp table wins because:

  • At the time of the select running, SQL Server realized it didn’t have any stats on the temp table’s contents
  • It automatically built statistics on the temp table, thereby learning the data distribution & contents of our one whopping row
  • It understood that the contents were Location = “India”
  • It looked up India in the Users.Location statistics, and realized that’s a biiiig location
  • It built a brand new query plan for the second query, and that new query plan was designed specifically for popular locations like India

However, this is only one case! I don’t want you drawing complete conclusions that temp tables are always better, because they’re not. In this specific example, I got a fresh execution plan based on the values I’m looking for, but that is not always the case. Even when it IS the case, you’re still dealing with what’s effectively OPTION (RECOMPILE), which can be a real pain in the processor.

So like I said in the beginning, Common Table Expressions are awesome because they let SQL Server reorder processing in whatever way it deems to be the most efficient for your current data distribution, on your current version of SQL Server. Default to CTEs.

But when SQL Server gets that process wrong, switch to temp tables.

To hear other peoples’ opinions on temp tables, check out the comments in this month’s T-SQL Tuesday invitation from Jeff Taylor. This month’s topic is temp tables, and as bloggers pour their hearts out, they’ll leave links over in the comments.

View Details

Today I’m hanging out in the dining room, or what would normally be a dining room, but we use it to store a 1992 Honda Beat. I explain why, and then take your top-voted questions from https://pollgab.com/room/brento. The audio on this one is a little tinny – the room is super-echo-y and I don’t think the camera picked up my lapel microphone. Sorry about that!

  • 00:00 Start
  • 01:37 RollbackIsSingleThreaded: Hi Brent! The editor says my articles are “edge cases” and prefers topics with mass appeal. I enjoy writing advanced SQL Server articles, such as “Avoiding Plan Cache Bloat,” rather than beginner articles like “How to Download SSMS 22.” How should I proceed?
  • 03:06 Rey Q&A: I recently watched one of your videos where you said that enabling in-memory OLTP on a database is a bad idea because it causes persistent performance issues. Does that mean that there’s no practical use cases for the feature?
  • 04:42 retired dba: My last employer wanted to consolidate several vendor supplied db’s under 1 server. My previous employers never did this (possible resource contention, security issues, upgrade issues, problem/bug reporting/resolution etc.). What say you?
  • 06:02 Bibi: Do you think regular SQL Server will ever get the auto index tuning that Azure SQL DB has or is this feature more of an enticement to get users off traditional SQL Server and into Azure SQL DB?
  • 07:15 AllOnSSDs: Under what conditions, for a database on all SSDs, would you recommend reducing the fillfactor on an index?
  • 08:15 Logzilla: Our OLTP app runs on AWS RDS SQL Server Multi-AZ. Transactions take ~40 ms, but every 5 minutes latency spikes to nearly 1 second for all requests, apparently during log backups. How can we confirm the cause and reduce the impact?
  • 10:33 Serhat: Our dev team put too many NC indexes on a given table despite DBA warnings. Is there a good way to quantify the impact of too many NC indexes for a table?
  • 11:36 Lazarus: Do you see many clients with certs on their SQL Server? Is it really necessary behind the firewall?
  • 12:40 Sir Index Alot: What are your favorite use cases for Copilot in SSMS?
  • 14:19 Dopinder: Does upgrading from SQL standard edition to enterprise edition require a reinstallation? Any risk in doing this?
  • 15:35 Bibi: What was your experience with natural language query for SQL Server back in the day? How was it secured? Will we see it make a comeback now that AI is more mature?

View Details

Over the years, tables – like your waistline – tend to get bigger. We keep tacking on more and more columns, one at a time, in order to handle app needs. It’s easier to add “just one more column” than it is to break things off into a whole separate table.

When you’re only handling a few rows at a time, like transactional insert/update/deletes and one-row selects, the overhead of these additional columns isn’t a big deal. SQL Server can dive into that one row and just fetch it, and since it sits on a single 8KB page anyway, the number of columns doesn’t affect single-row operations.

However, when you need to read multiple rows, the more rows you need to read, the more these extra columns will affect the overhead of the operation. This kinda thing is best illustrated with one of my Database Animations showing the difference between an index that only has Id and DisplayName, versus one that includes a bunch of wider string columns:

▶ Watch the animated version of Wide Rows Seek Vs Scan

I am amused by the AI’s final comment: “wide columns ride free on seeks.” Alrighty then. That certainly sounds like something I’d say. (I use Claude Code to build these animations: we storyboard them out together, and then it handles the details, and surprises me with little tidbits like that.)

As your rows get larger and larger – either due to more columns, or wider columns like JSON and XML, or both – SQL Server is forced to keep an eye on each row’s length. If the row can’t fit on an 8KB page, SQL Server automatically moves that data off-row.

As long as you’re not touching that off-row column – like if you’re not selecting or updating it – then the off-row column doesn’t impact the number of reads you need to do. That’s pretty cool, and it means that I don’t mind if people just store JSON data without manipulating it, and they only fetch it when they need it.

If you wanna be proactive, and if you’re sure that most operations don’t need those large columns, you can even tell SQL Server that you want large columns stored off-row by default, even when the row sizes are small. Check out sp_tableoption:

EXECUTE sp\_tableoption 'dbo.Users', 'large value types out of row', 1; Let’s get animated. On the left side, we have a table where all the wide columns stay on-row, and on the right, we’ve used sp_tableoption to force them all off-row, onto their own pages linked by a pointer:

▶ Watch the animated version of Off Row Storage

As long as you’re not selecting *, this option makes more sense, especially for big string columns like JSON, XML, and (N)VARCHAR(MAX) that you only grab when you’re pulling specific individual rows out of the database. The Users.AboutMe column is a great example: we ain’t running reports on AboutMe contents, nor using it for filtering, just outputting it when rendering a specific user’s profile page.

That sp_tableoption setting only takes effect on newly inserted/updated rows. If you want it to apply to the stuff that’s already in the tables, you’ll need to do an index rebuild.

View Details

Is your company hiring for a database position as of August 2026? Do you wanna work with the kinds of people who read this blog? Let’s make a love connection.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it.
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • It has to be a data-related job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Every SQL Server performance tuner eventually faces the same question: is this normal, or is something wrong?

The answer starts with 3 numbers about your SQL Server:

  • How fast it’s going
  • How hard it’s working
  • How big it is

On August 19, I’m doing a free webcast with JAMS Software to show you exactly where to find those numbers and what a “normal” range looks like for each one. Register now.

View Details

It’s official: SQL Server 2022 was the last release for SSRS.

At SQLBits this week, Microsoft announced that SQL Server 2025 won’t include SSRS.

Instead, all SQL Server 2025 customers will get free licensing for the on-premises Power BI Report Server (PBIRS.) The same license key you use to install 2025 will also work to activate PBIRS.

Microsoft’s got links on how it’ll work:

  • FAQ on the change – like why they’re doing it and how licensing will work
  • How to migrate from SSRS to PBIRS
  • How to migrate your RDL reports to PBIRS

Like any transition, there’s going to be manual work involved. Some data sources aren’t supported, and some SSRS features (like linked reports) aren’t supported. It reminds me of the DTS-package-to-SSIS conversion years ago, which even spawned small consulting companies that focused exclusively on that kind of work because there was so much of it. This transition will keep Microsoft partners busy for a few years.

I don’t do any reporting work, but I think the change makes complete sense for Microsoft and for folks who want better reporting. The change log for Power BI Desktop and for Power BI Report Server make it clear that Microsoft’s been investing way more in those products, whereas SSRS hasn’t gotten any love in years. I have fond memories of SSRS from 20 years ago, back when it came out and quickly decimated the market share of Crystal Reports. However, the writing’s been on the wall for quite a while. Power BI’s where the action is.

So, does this mean the gradual end of the free-in-the-box BI bundle that emerged in 2005: SQL Server Analysis Services, Integration Services, and Reporting Service? Those tools have all steadily declined in usage. Well, SSAS gets improvements in SQL Server 2025, but SSIS’s 2025 changes seem to be more about removing stuff than adding it. Might SSIS be next on the chopping block?

My guess is that SSRS’s ending was easier because Microsoft already had a fully on-premises solution in PBIRS. However, fully on-premises folks don’t have a Microsoft solution to replace SSIS yet. The closest thing they have is a self-hosted integration runtime, but the control is still dependent on the cloud. Announcing the ending of SSIS would be harder if Microsoft doesn’t have an alternative, so rather than ending it outright, they’re just stripping away stuff they don’t want to support (like Attunity and Hadoop.) Given that SSIS gets much less attention from end users (as opposed to reporting apps), Microsoft will probably let SSIS soldier on with zero development effort, like Service Broker. If it works for you, great – keep using it! But just know that the writing’s on the wall for this one, too.

View Details

I’m on a Med cruise, and I stopped the boat today in Corsica to make sure your questions from https://pollgab.com/room/brento got the answers they deserve. I started by mentioning that I’m using a 360 degree camera, but the file size on that video was so huge that I couldn’t upload it from the cruise ship, so you just get the 180 version.

Here’s what we covered:

  • 00:00 Start
  • 01:36 chandwich: Hey, Brent. At what point in your career did you start to feel truly confident in your ability to solve problems you have not seen before? Was there a specific “aha!” moment? Did that contribute to your decisions to move into consulting?
  • 04:35 Erez Yaar: Hi Brent, following your course i have ran sp_blitz on a freshly recovered database. I have got around 450 messages “Leftover Fake Indexes From Wizards” but no indexes to delete (only the statistics shows the same index names. The script on the URL return nothing.
  • 05:48 TechDB: Hi Brent could you pls brief the use case of CDC and Change data capture
  • 07:11 Ricardo: What are your recommended questions to ask the potential employer in a DBA interview?
  • 07:47 AG Avoider: Is it any kind of bad practice to use the same file share as an FCI Quorum witness and as your log shipping storage?
  • 09:02 Daniel: A third party application inserts millions of rows to mssql one by one. How to optimize the speed export process if a client code cannot be changed? I’m considering using memory optimized non durable tables and then move data to standard ones.
  • 10:26 gserdijn: Hello Brent. One of my servers has almost 20% stolen memory. Any pointers how I can find the culprit? A friendly person suspects it might have something to do with large, mostly unused, memory grants.
  • 11:58 MyTeaGotCold: How can I keep on top of columnstore maintenance when measuring fragmentation takes too long? My columnstore indexes are partitioned and huge, so Niko’s scripts take 20+ minutes per index to report fragmentation.
  • 12:54 Srinivas: In Query Store reports , large number of system queries (Microsoft related) shows up . For example queries with high CPU . Is there a way to bypass these in GUI . Is there any way to improve system queries by creating indexes or statistics ? Require more filtering options in QS
  • 14:47 Ben: Hey Brent, What are your thoughts on SQL Server on Linux? Have you seen much adoption, and do you think it’s a good direction for SQL Server?
  • 15:41 NotARealDBA: My app has an EF query that pages on a complex subquery. SQL will produce a Top N Sort operator if I inline the paging variables, but parameterized it requires a Top-Sort which spills and kills performance. Is there anything I can do that doesn’t require fighting EF? Thanks 🙂
  • 17:15 Jonathan: Hey Brent! Just curious—do you have a college degree, or did you go a different route into tech?
  • 19:20 chris: The company I work for blocks all of the AI providers as well as Copilot and even sites such as Notion which have a paid AI option available. Do you think their stance on these tools may change as they become more embedded with the way people work?
  • 20:14 I’mTrying: Given that new versions of SSMS and drivers are opting for security by default, are companies moving towards using CA signed certificates on their SQL Server instances? If it is best practice how are enterprises managing hundreds of SQL Servers and expiring certs?
  • 21:27 Potato with an e: I’m a new employee(a dev, not dba) and the DB’s have nolock hints all over the place. Eww. No RCSI. I brought up implementing RCSI and they said you can’t implement RCSI without removing all no locks first. Any techniques for continuing the conversation?

View Details

How often do you run backups, corruption checking, index maintenance, and statistics updates?

Click here to take the anonymous poll.

After you fill it out, you’ll be able to see the average responses from other folks. I’ll circle back next week and share the answers, plus chime in with my thoughts.

Update – I’ve closed comments on the post to make it clear that we’re doing a poll here, not asking for text answers, so we can deal with data instead of feelings. WINK WINK

View Details

Indexing can make or break your SQL Server performance. You need just the right balance: enough indexes to speed up your queries, but not so many that they drag down your inserts, updates, and deletes.

Join me as I introduce the “5 & 5 indexing guideline” — a practical approach to tuning indexes for maximum efficiency and minimum contention. Through real-world demos, I’ll will show how a single poorly chosen index can bring your system to a crawl with blocking issues.

Whether you’re troubleshooting slow transactions or proactively tuning your SQL Server for performance, this session will give you actionable strategies you can use immediately.

Who should attend? DBAs, SQL Developers, Database Engineers, and anyone responsible for SQL Server performance.

You’ll learn:

  • How to strike the right indexing balance
  • The “5 & 5” guideline and why it works
  • How to spot and resolve blocking caused by indexes
  • Real-world tuning tactics you can apply today

Register here for this free webcast sponsored by Idera. See you there!

View Details

I’ve always wanted to see the Barcelona Pavilion by Mies van der Rohe, and by happy coincidence, I ended up walking right past it while visiting Barcelona! It’s one of the most important beginnings of modern architecture, and I loved it. I brought you along with me and talked through your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 02:22 James: Hi Brent, I noticed in your last Office Hours session that your shoes looked huge! Do you have big feet? Just curious—what shoe size do you wear?
  • 03:30 Jerry: You mentioned a professional association for SQL Server during your last Office Hours. I’ve also heard about the PASS Summit—are they related?
  • 04:40 MyTeaGotCold: Are Availability Groups the hardest thing in all of SQL Server? It’s as if you can’t debug them without a very deep knowledge of SQL Server’s internals.
  • 07:02 Raja: Hi Brent! How do you create a nonclustered index or alter a clustered index on a large table where blocking is unacceptable to the system?
  • 08:17 DataBarbieAdministrator: Hi Brent! What was your worst experience with a customer – and how did you handle it? Thank you for all the (great!) free work you do for the community!
  • 12:28 Caught Brent’s Cold: Are CAL licences permanent? The official licensing guide was no help.
  • 13:41 Q-Ent: Hi brent, during your consulting career have you ever faced a satiation where a client or a department by the client challenged your knowledge or your competency?
  • 16:02 Dankula Flow: Should I treat the Blocked Process Report like Query Store and turn it on by default? I’m unclear on its performance costs.
  • 17:15 BA with DBA Hobby: I have separate disks for the database, log files and TempDB. When I switch our production DB from Simple to Full recovery mode the latencies on the database disk go wild. I would expect the latencies on the log files to go up not on the database. What could this be?
  • 18:40 World Peace: Hello dar Brent! The following scripts need xp_cmdshell: sp_allNightLog, sp_AllNightLog_Setup, sp_Blitz, sp_DatabaseRestore. xp_cmdshell is not a supported feature in AZURE Serverless and SQL Server Managed Instances. Is there a work around or a plan to fix this in the future?

View Details

There’s a secret theme to the questions I hand-picked from the queue at https://pollgab.com/room/brento. Normally I just take the top-voted ones, but today, see if you can spot the thing they all have in common:

Here’s what we covered:

  • 00:00 Start
  • 01:51 Tivan: Hi Brent, I’m facing a deadlock in MS SQL Server with “ORDER BY DESC” on a primary key (clustered index) during a read, conflicting with an insert on the same table. Is this related to descending scans? I couldn’t find a clear explanation. Could you share some thoughts? Thanks!
  • 03:19 ddev: Sometimes it happens that in a blocked process report I can see a frame that I know cannot be in a stacktrace (I know it is not called from that procedure). What does it mean ? It is bug I can fix ?
  • 04:38 Asking2much: Occasionally when tempdb is heavily hammered, sp_blitzwho gets an error of Lock request time out period exceeded (1second) due to tempdb.sys.sysschobjs.clst index being blocked. Would you be ok with setting the max lock_timeout value to 15 seconds? No issue with blocking liveplan
  • 07:14 Gary Numan: When tasked with fixing overall SQL VM performance with cloud hardware, what are your pros and cons of increasing server memory vs upgrading disk SKU? Which do you see more of?
  • 08:23 Vahid: Hi Brent I’ve been learning SQL DBA for about a year, mainly through tutorials. I feel I lack hands-on experience. How proficient should I be in T-SQL for this role? What’s the best learning path to improve my admin skills and problem-solving? Any advice is appreciated!
  • 09:24 Call Me Ishmael: Over a decade ago, when I “cornered” you at a SQL Saturday in Washington, DC, in-between sessions, I asked you about SCHEMAs, which at that time you were adamantly against, albeit humbly, belying your rock-star status. Are you still against the use of schemas?
  • 10:58 Jersey DBA: My company has a 3-node HA cluster. The third node is read-only for reporting. Why do we still sometimes see latency and blocking on that node with queries using the “with nolock” hint.
  • 13:30 KyleDevDBA: Hi Brent, What would you recommend when one DBA thinks another DBA isn’t pulling their weight? Is there a certain thing you look at to either prove or disprove this?
  • 15:58 CuriousDBA: Hello Brent. I see that you can use sp_blitz output to a table locally. Is there a way to store all that information centrally by running sp_blitz command against a list of all servers so that I can create a report for all critical issues across all my servers?
  • 17:56 Tim: If sql server becomes overwhelmed with locking / blocking issues, is there a way to give the server a break and allow it to catch up ?
  • 18:50 RacerX: What’s your opinion of NVME ultra disk when you are stuck with low memory (128gb) for multi TB database in Azure SQL VM?
  • 19:36 Milind: Hi Brent, Will there be any difference in join where column with regular index versus filtered index (where table has size and good number of rows)?

View Details

SQL Server Management Studio v21 Preview 1 is out and let’s give it a quick whirl. It’s installed with the Visual Studio installer. That doesn’t mean Visual Studio is installed or required – it’s not – it’s just that the SSMS team is leveraging the work that the VS folks have put in over the years.

After installing, you’re prompted to sign in to sync your SSMS settings across devices, but there’s a Skip link. I do wish there was a “skip this forever” link, but whatever:

If you log in with Github, there’s a rather spooky-looking list of permissions that SSMS gets:

I’m a little suspicious as to why SSMS needs all that. Insert joke about least-privileged-permissions here. Anyhoo, after SSMS starts, to enable dark mode, click Tools, Options, put dark in the search box, and choose Dark in the Color Theme:

Presto! Dark mode:

Eagle-eyed readers will notice that is not exactly dark mode. Erin Stellato (the SSMS PM) asked y’all for patience as they gradually work through the screens, converting them to dark mode. Once you’re connected, things look better:

The thing over at the far right was in the old SSMS too, it was just disabled by default. It lets you navigate through long stored procedures easier. At the bottom right, there’s an “Add to Source Control” link, which doesn’t do anything for me despite being logged in with Github. I’m guessing I have to organize a project or something first – I’ll dig into that later.

Query plans are not in dark mode yet:

To get into source control, click Git, clone a repository. I’ll take the First Responder Kit for example:

And a few seconds later:

Emotional damage. Okay, maybe it’s because I just copy/pasted the URL straight from Github. I edited out the /tree/main part at the end of the URL, and the second time it appeared to go through, although the SSMS UI didn’t change other than now the title bar says ViewPickerAutoload:

Which is honestly awesome, because I loved the pickers, and anything that SSMS can do to help Mike, Danielle, and Frank load the truck, the better:

I’m just kidding, of course. Frank passed away a couple of months ago. If only he’d been alive to see the show grace the title bar of SQL Server Management Studio.

Look, the point is that SSMS v21 is still very, very much in preview. It will install side-by-side with the legacy version (ha ha ho ho), so you can use both. v21 doesn’t support Analysis Services, Integration Services, or maintenance plans, so if you rely on any of that, you’ll still need the old v20. There are also a list of known issues with the preview, and right now I’d say it’s still for us hard-core early adopters.

View Details

You are not ready for how weird my take is.

Last week at the PASS Summit conference in Seattle, Microsoft showed off the upcoming SQL Server Management Studio v21.

One of the most intriguing features is that it has Copilot built in.

No, not Github Copilot, that’s a different thing. No, not the Copilot in Visual Studio, either. No, not the Copilot that’s in the Azure portal either. SSMS Copilot is yet another version of the same basic concept: a text box where you can ask questions, and AI uses contextual awareness of your database and your query window in order to answer those questions. I don’t just like this feature, I adore it, because I already use AI every single day to get my job done. (This blog post is AI-free, as most of my posts are, but I use it for all kinds of stuff like T-SQL code review and refactoring.)

The Microsoft staff demoing SSMS Copilot at Summit (Erin Stellato, Bob Ward, Anna Hoffman) were very quick to point out its limitations:

  • It’s in very, very early preview
  • The functionality is incredibly limited so far – it can’t even read real-world query plans due to context size issues
  • The output, like any LLM output, is prone to errors and hallucinations – the output of all of the demos I saw had serious issues for production usage
  • It sends your database schema/config/queries to the cloud – but they’re very clear about not keeping or using any of it for training, and in the future, you may be able to use your own LLM endpoints on-premises
  • It’s going to take at least a couple previews before it’s publicly accessible, which means at least 6 months away
  • It doesn’t actually read the error messages and results that come back from the queries it generates

And that last part is where the wheels come off.

To understand the problem,we gotta revisit history.Remember when Books Online first came out? Of course you don’t, dear reader, because you’re young and attractive. But being one of the olds, let me tell you how it went.

We used to get the documentation in printed format, and then Microsoft began distributing it in electronic form as part of the installer. You could just hit F1, and browse the documentation in SSMS. Later, the documentation moved into HTML, and later still, the primary home for the documentation became Microsoft’s web site. Some users were horrified when they’d hit F1, and a browser built into SSMS would take them to Microsoft’s web site to see the most recent version of the documentation.

Eventually, people just stopped using F1, and they used Google. The limited browser built into SSMS was garbage, and it didn’t support the kinds of stuff modern users wanted to do, like view documentation sites that require Javascript, like Stack Overflow.

The web browser is still there in SSMS, but I can’t remember the last time I used it. It’s just too limited. And that’s what the problem is going to be with Copilot in SSMS.

The SSMS Copilot demos made it glaringly obvious.The demos consisted of:

  1. Open the Copilot window in SSMS
  2. Type something into it
  3. Copy a query from the Copilot window into the SSMS editor
  4. Run the query
  5. Get an error or results
  6. Go back to step 2, copying the error, results, or clarifications back over into the Copilot window, and keep the cycle going

Which, uh, is exactly what you can do with ChatGPT and other LLMs today, and I’ve been doing for months. You don’t have to wait. Go get started now. You can pick other LLMs if you like, including local ones if you’re paranoid about sending your company’s database schema and queries up to the cloud. You can use the latest and greatest cutting edge LLM models, way beyond what SSMS Copilot supports. You can send query plans up there for analysis.

Copilot in SSMS, when it eventually ships, is going to lag far behind – just like SSMS’s web browser does.

Oh sure, SSMS Copilot absolutely does have some advantages over copy/pasting stuff into ChatGPT, like automatically picking out which tables & indexes are relevant to your question, and running diagnostic queries on your server to fetch the metadata on that table or index. But those advantages seemed so small to me, especially given how long it’s going to take to get that product live – compared to just getting started right now with ChatGPT or your LLM of choice.

Don’t get me wrong: Copilot in SSMS is still a good idea, Just like Books Online distributed via local HTML files was a good idea way back when. It was a stepping stone, and Microsoft had to do it at the time, just like they have to put AI in all their developer tooling today. I just don’t think it’s the final AI product that we’re all going to settle on.

So what could be better?Here’s my prototype for a version of SSMS that includes AI:

I can hear your confused voice from here: “Wait, Brent, that looks just like today’s version of SSMS. You type what you want in the top pane, hit execute, and what you want comes out of the bottom pane.”

Exactly!

Why should users have to jump back and forth between two different input areas? Just type what you want!

  • If you type T-SQL, SSMS executes it against the database in question. If your query has an error, the AI reads the error, and tries to suggest changes to your query to get it right. If your query takes too long, AI suggests improvements to make it go faster.
  • If you type plain English that asks for data, the AI’s natural language to SQL capabilities fire up and write a query for you. This isn’t new: Microsoft’s demoed it already, but in the Azure Portal, a tool that makes no sense for data analysts to use.
  • If you ask for advice on your database, the AI runs diagnostic queries on your database, just like the Copilot demos we saw at Summit, and the results and advice appear in the Messages tab, with supporting evidence in the Results tab.

That simple, intuitive approach is harder to build in 2025. It’s much easier for Microsoft to ship Copilot as a separate SSMS extension, duct taped into a separate tab, and force users to copy/paste stuff back and forth between different text boxes and result sets. Copilot will even catch on temporarily in 2025-2026, just as the SSMS browser did, and you will definitely see me using it.

I’m just excited and looking forward to whatever comes next to replace it.

View Details

That face I’m making in the video thumbnail is priceless. YouTube randomly picks these, and I laughed out loud at this one. Anyhoo, let’s get to answering your top-voted questions from https://pollgab.com/room/brento:

Here’s what we covered:

  • 00:00 Start
  • 00:59 Mohit: Hello Brent, What options does a DBA have in terms of performance tuning when managing third party application databases which have lots of crappy SQL queries and no lock hints? Last but not least, thanks for your service to the community.
  • 02:11 MyTeaGotCold: Page fullness is very important, but sp_BlitzIndex never touches sys.dm_db_index_physical_stats and Ola only touches it in LIMITED mode. What am I missing?
  • 04:19 Tony Feuz: Lot’s of talk about linked servers and how we should not do that. One of your recent posts you mentioned to move the data to the same server and I want to confirm that cross server queries = bad and cross database queries on the same server = acceptable. Do I have that correct?
  • 04:48 Trudging Through A SQL Swamp: I swear that I watched a video of you demonstrating how using NOLOCK could return incorrect data. I have looked everywhere and can not find that video. I did find a very short blog post by you about it, but would like to see the video again. Is it still available?
  • 05:35 Crazy Harry: Who is the Itzik Ben-Gan of PostgreSQL?
  • 05:49 Paul Hunter: How do you properly setup Index maintenance using Ola Hallengren on an AG? My environment has one active Server and one inactive server for fail over. (You will most likely ask why I used an AG for this, I didn’t. It is just something I have to deal with)
  • 06:43 mailbox: What are the advantages & disadvantages to housing your Data Lake in SQL Server? I’ve seen many sites push towards housing data lake on some NOSQL DB.
  • 07:56 Juan Pablo Gallardo: Is it correct that performance is greatly impacted by the cluster size of the partition, ie. 8k cluster size is ideal?
  • 08:53 MuSQL: Hi Brent, Recently involved in a debate on LI with a .Net dev. who claims that Stored procedures are legacy and that new projects never use them. I feel the pain when migrating between DBRMs but also the benefit of not shuffling data back and forth. Whats your opinion on this?
  • 10:00 Dopinder: Does SQL row / page compression make up for the low drive performance in Azure? Has it got you over the finish line?
  • 10:54 ScenarioFromRealWorld: How can I let coworkers stop using Activity Monitor. Are there any new articles regarding this? Because I cannot see that AM is getting any better than before
  • 12:07 OracleIsDiffrent: After downgrade MSSQL2019 from Ent. licence to Sta.we noticed small perform. issues.Queries who do index seeks and scans are running slower.The execution plans are same, major diff. is execution mode on index operations.On Ent. where running in batch mode now I can see row mode.
  • 12:51 Yavuz: Hello Brent. I’ve been a DBA for over a year now and noticed that DBA’s don’t really write too many queries. How did you get good at writing long @$$ sprocs and T-SQL while being on the data administration side? It’s mostly developers and BI folks writing the queries, not the DBA
  • 14:39 Bruno: What do you think of transactional replication? Would it be better to use Log Shipping instead? We have a publisher distributing a lot of publications and we experience some performance issues on a regular basis. Thanks Brento and Cheers to the DBA great family.

View Details

I took the Graffiti Gulf 356 out to the Valley of Fire State Park to exercise it, and took your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 01:39 mailbox: Hey Brent! I’m really enjoying your prerecorded training classes. Quick question,I’m running sp_BltizCache @SortOrder = ‘reads’ on our DW server and receiving a priority 1 warning of Plan Cache Instability. How meaningful is this warning on a DW server?
  • 02:49 Briggers: Hi Brent. I have inherited an intense AG with 1 database, utilising an async read-only secondary. Is there a way to help reduce the size of a redo queue? For example reducing the number of checkpoints (Automatic) on the primary?
  • 04:00 DoesTimeReallyExist: Hi Brent! I prefer to learn SQL Server in depth instead of learning no-SQL or PostgreSQL and TimescaleDB. What do you think?
  • 04:31 Aksel: Duplicate Index How to explain a situation where there are indexes A (col1, col2) and B (col1, col2, col3, col4), and there is a query that checks the values of col1 and col2. If the query uses index A, no memory grant occurs. If the query uses index B, a memory grant occurs.
  • 05:31 Cameo: What are your pros / cons of using local time vs UTC time for OS clock running SQL Server? Which do you see more of out in the field?
  • 06:51 mailbox: My friend’s company pays only to license 4 cores enterprise(SA) on a reporting server. Best I can tell, we don’t need enterprise as of now. However, we might need it in the future. Is it a good idea to switch to Std edition on same budget, thus increasing core count?
  • 08:00 adba: I am seeing high CPU on a SQL server VM,I have added more cpu and tuned the query, but we still see the issue. What parameters do I need to monitor to show it is a problem on the host side.
  • 08:59 GenXerTiredOfTheBabyBoomers: You have probably got this question often, but getting up there in age/end-of-corporate-life, how does one become a consultant? I have decades of experience with MS SQL, Windows OS, and networks, yet have trouble crossing the great divide of corp to cnslt.
  • 10:18 SportsFan101: What are your thoughts on the new JSON data type in Azure SQL? Will we see this feature in the new on-prem version, SQL Server 2025?
  • 11:28 Bandhu: When doing row vs page compression for canned SQL, do most of your clients do all row compression or all page compression or some combination?
  • 11:48 mailbox: In your experience, when is it time to upgrade server hardware? Maybe I should ask, how often should we try to upgrade the server hardware of our SQL Servers? My friend says that they have VMs on hosts that are 8 years old.
  • 12:53 Juan Pablo Gallardo: In pure ERP environments, with no user queries or tasks outside the ERP, is it safe to say that any deadlock is responsibility of the ERP vendor to solve?
  • 14:06 Dopinder: What criteria do you use when evaluating standup desks? What is your favorite brand and model?
  • 14:44 Vasilis Hadjiloucas: Should I exclude my antivirus software from scanning my FILESTREAM container in SQL Server? What are the potential risks or benefits of doing so?
  • 15:17 CryingInTheCorner: Hi Brent, you still didn’t update most of your Mastering classes since Sql Server 2022 came out… :'(
  • 16:41 Dumb dude: If you had a server that was having a lot of resource contention and you were only allowed to add CPUs or Memory, but not both, without cost being factored into it, which would you pick.
  • 17:21 About the 356’s Graffiti Gulf paint job
  • 18:40 Dopinder: Can a single DBA manage a new SQL AG or is a team of DBAs recommended for AG administration? What do you see in the field?
  • 19:31 mailbox: What is it like to work as a DBA for a consulting firm? Is it just non-stop performance tuning fun? Or are their lots of nights and weekend work?
  • 20:50 Eddy Grant: When upgrading Azure SQL VM from 2019 to 2022, is it ok to do in place migration since we have snapshot backups or should we logship to new VM hardware?

View Details

I’m on a boat! We took an Alaska cruise with some friends aboard the Norwegian Jewel. En route to Icy Strait Point, Alaska, I took your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 01:40 RollbackIsSingleThread: Hi Brent! If a high-quality blog post involves original ideas, T-SQL, a great demo, and images to prove a point, but uses an AI tool like Grammarly or Google Translate to edit the content, Google might delist it. Any idea?
  • 03:27 MyTeaGotCold: Can you think of anything that the Service Broker is the best solution for? Modern alternatives seem better.
  • 04:37 JustWondering: Do you have a sense of what percentage of your followers are administering systems that are “custom built” vs “vendor app” dbs?
  • 05:13 Miss Minutes: Once SQL AG is stood up with two HA nodes and an offprem DR node, are SQL full backups necessary any longer?
  • 05:47 some_like_it_encrypted: Does people use Always Encrypted? I have the feeling that it’s quite an unused feature.
  • 06:53 chandwich: Have you ever successfully changed a database collation for a large database with numerous constraints? Any tips for doing this?
  • 08:43 Daniel Izzaldin: Hi Brent, do you have a course or do you know a course that teaches you how to become a Consultant.
  • 10:29 Logar The Barbarian: Hello! Is sp_DatabaseRestore expected to work with Azure/blob backups? From my review of the GitHub, it does not appear so. If not, what would you suggest for restores to other servers? I like sp_RestoreGene for same servers but it may not work for DR/test restores. Thank you!
  • 11:40 Laslzo: When an sp needs a long list of input id’s, do you prefer comma delimited string or a table value param with all the ID’s?

And that zipline that I mention in the video? Yeah, that was pretty awesome.

View this post on InstagramA post shared by Brent Ozar (@brento)

View Details

Is your company hiring for a database position as of October 2024? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

I recently asked you to leave a comment with your biggest database regret, and the comments were great! Here were my favorites:

Runners-UpThese 5 folks each won a Fundamentals Bundle lifetime access valued at $695:

Thirster42: writing code to help a team dynamically create sequences. they didn’t tell me they were going to generate millions of them so now the db is super hard to open in object explorer, run sql compare, or use auto complete tools.

Thirster42’s was literally the very first comment, and I laughed out loud when it came in. It’s such a good example of a regret. In theory, sure, you can dynamically create just about anything in SQL Server, but the more of them you create, the worse shape you’ll be in. It reminds me of Swart’s 10 Percent Rule.


Stefano: One of my first jobs as a consultant: critical production SQL Server with performance issues (slow queries, blocking), high workload (thousands of queries/s). To study the problem I decided to run a server-side trace. The idea was to capture a lot of types of events and not lose any records… Result: total block. No way to stop the task. Flurry of calls from customers… Not knowing what to do, I had to restart the server remotely..

I’ve been there too. I do wish there were more “are you sure you wanna do this” guardrails built into T-SQL commands. Those kinds of guardrails are common in GUIs, and in operating system text commands, but completely unseen in query language commands. (“Hey, are you sure you wanna run a delete without a where clause?”)


Alex: No pure SQL compatibility between different products. MSSQL, Oracle, PostgreSQL etc. TOP(100), LIMIT(100), FIRST(100).

At first when I read Alex’s answer, I thought to myself, no, Alex, this contest was supposed to be regrets about things YOU had done, but when I went back and reread the post, I realized Alex’s answer was totally legit. Better than that, Alex’s answer is one of my OWN top regrets about the database industry too, come to think about it! The languages are juuuuust close enough to be annoying, and just close enough that execs think that a migration will be easy. It will not.


SmartWombat: My first ever FORTRAN computing assignment at college (’67) just to input and store name, age, sex. Report on the invalid data. Next day I went back to the lecturer and said there’s nothing in the data to determine if they are an invalid or not. Cue red face when he explained it to mean incorrect data, as in not valid. Not data about invalids. Lesson learned on requirements gathering at a very early stage !

I laughed out loud at this one too because it took me a couple of reads to understand what “invalid” meant in this context.


Thomas Franz: On a previous job my coworker decided to not allow NULLs in from/to columns and to use a default value instead. Sadly he decided it to be 1899-12-31 for both, from and to, so you always had to write something as GETDATE() BETWEEN t.valid_from AND IIF(t.valid_to = ‘18991231’, ‘20991231’, t.valid_to)

Uuuuuuugh. Yeah, that would suck.


Grand Prize WinnerChris Wilson: My biggest regret is not starting a online presence. For over a decade I’ve followed the careers of many in the SQL community and thought I could do that and had grand plans to do so but never pulled the trigger. Like planting a tree the best time to start a SQL blog is 20 years ago. The second best time is today. I don’t know that it would have changed my career in any meaningful way but I do know it would have solidified my own knowledge in a very tangible way. “The best way to learn is to teach” as the old saying goes.

I felt guilty as soon as I read Chris’s regret because I knew I had to give him the prize, which happens to be a Fundamentals + Mastering Bundle lifetime access valued at $2,495.

I don’t care what your online presence is: a Github repo, a YouTube channel, a blog, a podcast, whatever – but pick one thing that works for you, and start doing it.

Get ‘er done.

View Details

Your accounting officeEvery year during November, we run a big sale all month long.

And every year, right after the sale ends, we get a bunch of panicked emails from people screaming, “I HAD NO IDEA YOU WERE RUNNING A SALE, I NEED MORE TIME, YOU HAVE TO EXTEND IT SO I CAN GET APPROVAL FROM MY 14 DIFFERENT DEPARTMENT HEADS AND GET A CHECK SENT BY BOAT FROM OUR ACCOUNTING TEAM IN TRISTAN DA CUNHA!” Followed by a lot of sad trombone noises.

This year, let’s make it a little easier by giving you some advance notice.

Here are the deals we’ll be running during November:

  • Fundamentals Classes: ~~$395/year~~ $195/year, save $200
  • Mastering Classes: ~~$995/year~~ $695/year, save $300
  • Fundamentals + Mastering: ~~$1,295/year~~ $795/year, save $400
  • Fundamentals + Mastering Lifetime: ~~$2,495~~ $1,795, save $700

And if you want to add on our apps, SQL ConstantCare® and the Consultant Toolkit, these bundles include those too:

  • Level 1 Bundle (Fundamentals + Apps): ~~$995/year~~ $695/year, save $300
  • Level 2 Bundle (Fundamentals + Mastering + Apps): ~~$1,595/year~~ $995/year, save $600

So now’s the time to coordinate with your manager. Here are a few questions that managers usually ask:

Can we pay via check or purchase order? Yes, but only for 10 or more seats for the same package, and the full payment (not just a purchase order or IOU) must be received before the sale ends. Email us now at Help@BrentOzar.com with the package you want to buy and the number of seats, and we’ll send you a quote to include with your check. Make your check payable to Brent Ozar Unlimited and mail it to 9450 SW Gemini Drive, ECM #45779, Beaverton, OR 97008. Your payment must be received before we activate your training, and must be received before the sale ends. Payments received after the sale ends will not be honored. We do not accept POs as payment unless they are also accompanied by a check in the same envelope. For a W9 form: http://downloads.brentozar.com/w9.pdf

Can we get discounts for group buys? Not during the Black Friday sale. These prices are as low as we go.

Can we send you a form to fill out? No, to keep costs low during the Black Friday sales, we don’t do any manual paperwork or sign up for your vendor system. To get these awesome prices, you’ll need to check out through our web site and use the automatically generated PDF invoice/receipt that gets sent to you via email about 15-30 minutes after your purchase finishes. If you absolutely need us to fill out paperwork, we’d be happy to do it at our regular (non-sale) prices – email us at Help@BrentOzar.com for details.

Sales will start November 1. See you there!

View Details

I took your top-voted questions from https://pollgab.com/room/brento while recovering from a late night of partying.

Here’s what we covered:

  • 00:00 Start
  • 01:00 VegasDBA: Loved the Always-On Availability Group Episode! You mentioned how awful the dashboard is for monitoring. Can you recommend any scripts, custom alerts, or dashboards to keep a better eye on things?
  • 03:26 SteveTV: Are there any tools or utilities to manage source control for SQL Agent job definitions?
  • 04:21 SHA256: How do you feel about MongoDB? Is there ever a reason to use it over SQL Server?
  • 05:50 JoseDBA: What metrics should I show to my boss when asking for a new dba in my team. We are 3 and manage around 180 servers with over 3000 DBs. I read your post of “how many dbas you need” but I don’t know how to properly communicate that. Thanks!!
  • 08:49 JoseDBA: How to keep server level objects in sync when using availability groups. Is dbatools the best option?
  • 09:46 Discussing my Anthony Bourdain painting by Cassie Ott
  • 11:52 Elon: Why don’t you own an electric car?
  • 14:27 MyTeaGotCold: When I’m writing a new stored procedure and make a compile-time syntax error, the error’s line number is always wrong. What’s the trick?
  • 15:25 Sigurður: Should SQL VM DBA’s also be required to know how to create the underlying infrastructure (VM, cluster, disks)? Is this a unicorn trait?
  • 17:15 happydba: what happened to groupby (the online conferences)? they were great 😀
  • 18:57 AppleUser: How do I convince my security team not to run EDR on my SQL Server cluster?
  • 20:39 Bandhu: For Azure SQL VM’s, is large memory or fast disk more of a dollar premium?
  • 21:06 Ninja: I’m struggling getting my SSMS to connect my on-prem SQL Server to Azure Blob Storage. Any advice?
  • 22:23 Panagiotis: Currently on SQL 2019 with log shipping HADR. Is it wise to simultaneously migrate to SQL 2022 / availability groups or should those be two separate upgrades?
  • 23:45 JerseyDBA: As someone who is younger (30+ years away from retirement) what’s the most important thing you think a DBA can do to future proof their career?
  • 25:38 Dopinder: What complimentary AI skills should the SQL Server and PostgreSQL DBAs be learning?
  • 27:21 Simon Frazer: Hi Brent, I love reading all your posts about career progression! How much time do you have to spend writing posts to keep your blog fresh?

View Details

Brent, Big Coat EditionYou’ve watched my free How to Think Like the Engine class that focuses on the small 1GB Users table.

Let’s take things up a notch by using the ~164GB Posts table full of questions & answers. You’ll learn:

  • What PAGEIOLATCH waits are
  • Why you can’t usually fix them by just adding small amounts of memory like 16-64GB RAM
  • Why key lookups aren’t a big deal (compared to the alternative)
  • Why SELECT * isn’t as bad as it’s cracked up to be
  • Why big data also means slow writes on storage

Join me next Thursday for a free webcast sponsored by Pure Storage. See you there!

View Details

About 10 years ago, Microsoft made changes to the Cardinality Estimator (CE) which caused some problems for SQL Server upgrades. When folks upgraded to SQL Server 2014, they also casually switched their databases’ compatibility level to the latest version, because for years that hadn’t really affected query plans. They just figured they wanted the “latest and greatest” compat level, without regard to the effects. That backfired badly when they suddenly got 2014’s Cardinality Estimation changes.

So for several years, whenever someone upgraded from older versions, and they complained about performance, the stock community answer was, “Change your compatibility level back to what it used to be.” In many cases, that just solved the problems outright, leading to blog posts like this and this.

Even today on SQL Server 2019 & 2022, this advice is still relevant! If you mess around with compatibility levels, you can absolutely change cardinality estimations in ways you didn’t expect.

One amusing example is SQL Server 2022’s cardinality estimation feedback. Even if your workload has been on 2014+’s “new” Cardinality Estimator for a while, 2022’s CE feedback can change cardinality estimations back to older versions! That’s a complex example, though, and I’d rather stick to simple examples for here on the blog.

Simple Example Where 2022’s CE ImprovedLet’s say our code uses a scalar function that just implements an RTRIM:

CREATE OR ALTER FUNCTION dbo.CustomTrimmer (@Input NVARCHAR(40)) RETURNS NVARCHAR(40)ASBEGIN DECLARE @Output NVARCHAR(40) = RTRIM(@Input); RETURN (@Output);ENDGO Starting with SQL Server 2019, SQL Server can attempt to inline that scalar function. Not only does that affect the shape of the execution plan, but it also affects the estimates.

Let’s see it in action with the largest Stack Overflow database. We’ll start by building an index to support our query, and then we’ll run the same query in two different compatibility levels – first 2016, then 2022:

CREATE INDEX DisplayName ON dbo.Users(DisplayName);GOALTER DATABASE [StackOverflow] SET COMPATIBILITY\_LEVEL = 130 /* 2016 */GOSELECT TOP 101 * FROM dbo.Users WHERE dbo.CustomTrimmer(DisplayName) = 'alex' ORDER BY Reputation DESC;GOALTER DATABASE [StackOverflow] SET COMPATIBILITY\_LEVEL = 160 /* 2022 */GOSELECT TOP 101 * FROM dbo.Users WHERE dbo.CustomTrimmer(DisplayName) = 'alex' ORDER BY Reputation DESC;GO The actual query plans:

First off, the good news is that 2022 absolutely smokes 2016 simply because it inlines the function. The query can complete in about 1 second, as opposed to 2016’s 1 minute 16 seconds. But set that aside for a second and let’s look at the cardinality estimation changes.

The top plan (2016) does a clustered index scan because SQL Server 2016 made a hard-coded assumption that 10% of the rows would match our filter. The first operator (top right) estimated that 22,484,200 rows would come out of the clustered index scan, and then the second operator (the filter) estimated that 2,248,420 rows would match.

Gotta love those hard-coded estimates at exactly 10% because they’re easy to spot, but I do wish they had a yellow bang on ’em so that SQL Server would warn us that it’s making up estimates out of thin air.

The bottom plan (2022) uses the index AND it gets absolutely beautiful, bang-on cardinality estimates. The first operator (top right, index scan) estimated 18,882 rows would come out.

The haters will say, “Brent, that’s not fair, that’s a different feature and it’s not the Cardinality Estimator.” They’re wrong, of course: the important part is that things have been changing all around the Cardinality Estimator, changing its inputs, and so as a result it’s common to see different estimations coming out of the CE with each subsequent version.

Simple Example Where 2022’s CE WorsenedIn the first example, our simple function used the exact same NVARCHAR(40) that our table’s DisplayName column uses. However, what happens if we change the function to use a more generic datatype, like NVARCHAR(MAX)?

CREATE OR ALTER FUNCTION dbo.CustomTrimmer (@Input NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)ASBEGIN DECLARE @Output NVARCHAR(MAX) = RTRIM(@Input); RETURN (@Output);ENDGO We’ll run our queries again, and look at their actual execution plans:

Now, SQL Server 2022 ignores the index. Why would you ignore the index in a query like this? Because you estimate that too many rows will come back, making the key lookup too expensive. But… look more closely at 2022’s execution plan. How many rows did it actually think were going to come out after the function’s filter?

Just one.

I have no idea what the sam hell bug this is, or which part of the engine it’s in – whether it’s the CE or scalar function inlining or the query optimizer. All I can say is that the estimate is hot garbage. As a result, the sort spills to disk because SQL Server didn’t allocate enough memory to sort the rows that actually came back.

So you can’t even say, “Thanks to 2019, scalar functions get inlined, so estimates are more accurate.” They’re not. They’re all over the place, even in simple cases like this where we’re just changing the length of a datatype. (Again: the example here in the blog post is purely to talk about cardinality estimation, but at least 2022’s query runs way faster in this case because the function gets inlined.)

The Moral of the StoryThe moral of the story: keep your grubby fingers off the compatibility level switch until you’ve followed my migration instructions.

To learn more about topics like this, attend my PASS Summit pre-conference workshop in Seattle, Tuning T-SQL for SQL Server 2019 and 2022.

View Details

If you’re using TRY/CATCH to do exception handling in T-SQL, you need to be aware that there are a lot of things it doesn’t catch. Here’s a quick example.

Let’s set up two tables – bookmarks, and a process log to track whether our stored proc is working or not:

DROP TABLE IF EXISTS dbo.Bookmarks;DROP TABLE IF EXISTS dbo.ProcessLog;CREATE TABLE dbo.Bookmarks( URL VARCHAR(50));GOCREATE TABLE dbo.ProcessLog( ProcessDate DATETIME, StatusMessage VARCHAR(50));GO And create a simple stored procedure that adds a bookmark, and tracks whether it was successful:

CREATE OR ALTER PROC dbo.AddBookmark @URL VARCHAR(50) ASBEGIN BEGIN TRY INSERT INTO dbo.Bookmarks VALUES (@URL); INSERT INTO dbo.ProcessLog VALUES (GETDATE(), 'It Worked'); END TRY BEGIN CATCH INSERT INTO dbo.ProcessLog VALUES (GETDATE(), 'It Failed'); END CATCHENDGO When you execute the proc, it succeeds, and a row is written to ProcessLog:

But if someone adds a new column to our Bookmarks table:

ALTER TABLE dbo.Bookmarks ADD BookmarkedOn DATETIME; And we try to run our stored proc again, it fails:

Because the stored proc’s insert statement didn’t explicitly list the columns in the Bookmark table:

INSERT INTO dbo.Bookmarks VALUES (@URL); Okay, that’s bad code – but did the CATCH come into play? Check the table contents:

There’s no row in ProcessLog saying that the process failed! What happened? Wasn’t our CATCH supposed to insert a row there?

Catch only catches SOME errors.Early errors aren’t caught, like errors when the query is being compiled. In this case, when SQL Server was building an execution plan for the stored procedure, SQL Server couldn’t build a valid execution plan because there’s no way for it to execute the insert. The compilation failed, which technically means the query wasn’t executed – even though to you and me and our app users, it was executed.

Low-priority errors aren’t caught, like under severity 10. Those are just considered informational messages.

High-priority errors aren’t caught, like severity 20 or higher. Those terminate the connection altogether.

Right about here is where you’re expecting me to give you a magic bullet that fixes these problems, but instead, I have to give you a monster amount of documentation. Check out the epic posts Error and Transaction Handling in SQL Server Part 1, Part 2, and Part 3 by Erland Sommarskog. They’re monster posts, and I have to be honest with you, dear reader, I haven’t ever read them cover to cover. This is one of those times where I’m glad I have a fake job, aka consultant, where I can just say, “If our stored procedure’s business logic is really that critical and complex, it’s time we move that processing over into an application language like C# that has better error handling and testability.”

View Details

I went through your top-voted questions from https://pollgab.com/room/brento plus hit live ones from the TikTok viewers.

Here’s what we covered:

  • 00:00 Start
  • 00:52 chandwich: If SSMS had a dark mode option that was equally as good as the existing light mode, would you use it? Any idea why it doesn’t exist yet? RE: The on-call DBA that doesn’t like being blinded at 2:00 AM by SSMS.
  • 06:06 DBA JR: Hi, Brent what do you think about DP-300 Exam Certification or other certification? do you think is effective for finding a DBA job in the US or Europe? Is it important for companies?
  • 09:01 MyTeaGotCold: What are the biggest disadvantages of using RDS Microsoft SQL Server instead of an EC2?
  • 11:01 Yukio: What are the top skill gaps you see in SQL Server DBAs?
  • 14:20 DataGuy: Assuming a table does not have range scans nor ORDER BYs, why should a clustered index be added? HEAPs get a lot of hate, but maintaining them nightly with enterprise edition isn’t that big of deal. Blindly adding CX to the PK field(s) means worse performance for the NC indexes?
  • 16:36 Ozan: Hi Brent, when a SQL Server Patch gets released it makes sense to wait a while before deploying because it might be buggy or might have other unexpected surprises. Do you know a reliable source or community where one can check if a patch is „safe“? Thanks
  • 18:02 Meg Thomas: Does drive block size matter when using NVME SSD in SQL cloud vms ?
  • 19:35 Wiron: When should you use a stored procedure?
  • 20:24 zxta: How does a database like Redis work?
  • 21:17 Ross: When I’m developing an application, what indicators would trigger me to use SQL Server over Postgres?
  • 22:53 User: Do you have any plans for Postgres training?
  • 23:20 Tadim: What about storing JSON in MongoDB versus Postgres?
  • 23:58 Ailos: I use SQL Server clusters on physical devices. What IO values should I look for?
  • 25:25 Tim: How do you land a SQL job?
  • 28:03 Tadim: Do you have any experience with SingleStore?
  • 28:51 Raphra: If ChatGPT or Gemini used your online blogs to train models, would you be ok?
  • 30:55 Yoichi Asakawa: What is your opinion of NetApp files for Azure SQL VM?
  • 32:10 ThreeDaysGrace: How do I avoid losing connectivity between databases and applications on failover?
  • 33:58 User: What’s the difference between leaderless and multi-leader replication for databases?
  • 34:42 User: Why should I limit the connection pooling on my server?
  • 35:25 Clip: Can you talk about indexing?
  • 36:43 Steve Harrington: Is it recommended to use allocation unit size of 64kb on temp db drive for Azure SQL VM? How do you do this if the drive is ephemeral?
  • 38:00 OMGTiko: You should talk about why the best data warehouse is a lakehouse.
  • 39:29 A discussion about TikTok’s algorithm
  • 40:04 Ristos: I’m getting an error in MySQL, how do I fix it?
  • 40:27 UnderTheC: How do I use Redis to cache data effectively?
  • 41:40 Aidos: When I have different plans for the same query, do you have videos for that?
  • 42:35 Fioma: Can you talk about partitions?
  • 43:42 Leolog: Any recommendations on how to learn architecture, like data warehouses and lakehouses?
  • 44:06 ThreeDaysGrace: Wow, Brent, how are you not losing such inspiration for new technology?
  • 46:09 Gambit: How do you determine the correct amount of TempDB files and their sizes?
  • 47:08 JChandra: It’s been a while since I looked into SQL Server internals. Can you scale it out horizontally these days?

View Details

Is your company hiring for a database position as of September 2024? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Today’s Office Hours had a ton of technical difficulties because it was my first live stream on both Twitch and TikTok. The first few minutes were cut off, and you can’t see the questions onscreen. Nonetheless, there are good answers in here, so let’s do it:

Here’s what we covered:

  • 00:00 Start
  • 00:03 LivingTheDream: I’m the DBA for a medium sized city. We’re dealing with a ransomware attack and in 3 days every acct/pswd in our environement will get reset based on input from 3 security vendors. Do you have any suggestions for handling such a situation for others that may run into this issue?
  • 01:45 DB: I’m using SQL Server 2019 on-premises, and it feels like the quality of Cumulative Updates has gone down over the years.
  • 02:44 The People’s Elbow: What’s the closest you have come to getting violent with a database server?
  • 05:32 Addi_Fen_Tan: How do I learn Azure for a DBA role?
  • 07:01 Vishnu: I suspect we have unreported SQL Server instances running onprem and in Azure but not sure where they are located. What tool do you like to use for scanning for unreported SQL Server instances?
  • 07:51 Hal Jordan: Is there demand for a Postgres version of SQL ConstantCare?
  • 08:23 Stefanos: Is there automation for testing restores?
  • 09:34 IRDBA: Hi brent I have some table with 40 50 million record, reorganize indexes on that tables takes much longger versus rebuild?index optimize job failed because of reorganizing index .. Ive changed index optimize job to rebuild online and do not reorganize any indexes any more
  • 10:16 Lucy MacLean: Will the Crowdstrike issue cause more shops to ditch SQL VM and move to managed SQL (Azure SQL Managed Instance, Azure SQL DB, Amazon RDS, etc)? Will Crowdstrike recover from this?
  • 12:04 Addi_Fen_Tan: Is Ola Hallgren’s maintenance script what you recommend?
  • 13:16 Mattia: There’s been a lot of talk about CS disaster, but I can’t think of a disaster recovery strategy to avoid going down (except not using It, but that’s not for the DBA to say). I’m thinking that It was inevitable, am I missing something?
  • 14:50 Stefanos: What’s the best for a SQL Server VM: 1 core or 2, 8GB or 16GB RAM?
  • 16:11 Addi_Fen_Tan: How can a DBA be better at performance tuning and monitoring?
  • 16:41 S2ray: Where would you start if you wanted to start over in SQL database development after 9 years?
  • 17:38 user317: I’m about to hit Azure SQL DB’s 4TB limit. Would you recommend sharding or something else?
  • 19:02 john: What’s your view for running database servers on Kubernetes?
  • 20:30 JerseyDBA: A lot of people at my company use a subquery in the FROM clause of queries instead of using a WHERE clause in the main query. Does this by itself cause performance issues?
  • 21:28 Steve E: Hi Brent, How might we explain why queries that usually run OK sometimes experience regression performance wise. The queries do not have any parameters but are often full of famous T-SQL anti patterns. My theory is bad plan choice given too many options due to the anti patterns?
  • 22:27 Moldaver: Is YouTube office hours short form or long form more popular? Why is this?
  • 23:23 Addi_Fen_Tan: What are your thoughts on SQL Server 2022?
  • 24:03 One_of_the_Party_People: Hi Brent. Working with a client whose database is in Managed Instance. Creating a nonclustered index on a specific table causes database corruption. Tried completely rebuilding the table with no improvement. The same index builds fine in an on-prem instance. Any suggestions?
  • 25:09 Ricardo: Howdi Brent, I’ve a new customer with raw queries from an app server, that regularly run for over 10 minutes. They have no waits, and execution plans which look fine, ok indexing, and estimated-subtree-costs like 0.723. They execute almost instantly for me. Any ideas?
  • 27:11 David: Why is it that there exists so little content on in memory sql features? Is it due to the restrictions those features bring or is just not necessary to use them if you database is well designed?
  • 28:11 TD: What are your thoughts on Azure Managed Instances vs Azure SQL DB?
  • 29:01 Accidental DBA: Hey Brent, Is it acceptable to apply for jobs where some of the key skills are lacking but have others (given I’m upfront with them)? I find myself avoiding to apply to jobs currently, however, am capable/willing to learn. Just not sure the protocol on this type of thing.
  • 31:20 gserdijn: Got this VM 2019 Enterprise,130 GB Physical Memory and Datafile over 400GB. The MEMORY_CLERK (all the cached data) only has 30GB with all other clerks well below 1 GB, so I expected a much higher value. Is this normal behaviour for a quite busy instance running for a few weeks?

View Details

In this week’s Query Exercise challenge, I explained SQL Server’s 201 buckets problem. SQL Server’s statistics only handle up to ~201 outliers, which means that outliers ~202-300 get wildly inaccurate estimates.

In our example, I had an index on Location and perfectly accurate statistics, but even still, this query gets bad estimates because Lithuania is in outliers ~202-300:

CREATE INDEX Location ON dbo.Users(Location);GOSELECT * FROM dbo.UsersWHERE Location = N'lithuania'ORDER BY Reputation DESC; SQL Server estimates that only 8 rows will be found for Lithuania, when in reality 2,554 rows come back:

This under-estimation isn’t really a problem for this particular query’s performance, but when I’m teaching you concepts, I gotta teach you how the simple things break before I start getting into real-world specifics. If you can’t solve this simplistic version, then there’s no way you’re gonna be able to solve the real-world version, which we’re gonna get into in the next Query Exercise.

Solving It with a New Filtered StatisticI cringe when I type that heading out because it’s such a slimy solution. I’ll start with a simple version, and it’s actually something I hinted at you not to do in the challenge instructions because it’s a bad idea, but bear with me for a second.

SQL Server lets you create your own statistic on specific outliers by using a statistic with a WHERE clause, like this:

CREATE STATISTICS Outliers ON dbo.Users(Location) WHERE Location = N'lithuania' WITH FULLSCAN;GOSELECT * FROM dbo.UsersWHERE Location = N'lithuania'ORDER BY Reputation DESC; The query gets a new execution plan with bang-on estimates:

Okay, great – but like I mentioned in the challenge requirements, you wouldn’t actually do this in the real world because you’d probably have multiple outliers, not just 1. If you only had 1 big outlier, then… it’d be in your regular 201 buckets!

Instead, if we’re going to solve this with a filtered statistic, we need to create our own manual statistic for the next 200 outliers. First, let’s write a query to find outliers 201-400. Keep in mind, I’m not guaranteeing that they’re not in the existing Location statistics yet – I’m just trying to illustrate how we would find Locations with a large population, but that aren’t in the top 200:

SELECT CAST((N'N''' + Location + N'''') AS NVARCHAR(MAX)) AS Location FROM dbo.Users WHERE Location IS NOT NULL AND Location <> '%''%' /* Exclude ones with a ' in it, since that'd break our dynamic SQL */ GROUP BY Location ORDER BY COUNT(*) DESC OFFSET 200 ROWS FETCH NEXT 200 ROWS ONLY To keep things simple, I’m not using a tiebreaker here. (There are only so many things I can cover in a blog post, and at the end of the day, remember that the focus here is on statistics & outliers.)

Next, let’s use that to build a string that will create our filtered statistic:

DECLARE @StringToExecute NVARCHAR(MAX);WITH OutlierValues AS ( SELECT CAST((N'N''' + Location + N'''') AS NVARCHAR(MAX)) AS Location FROM dbo.Users WHERE Location IS NOT NULL AND Location <> '%''%' /* Exclude ones with a ' in it, since that'd break our dynamic SQL */ GROUP BY Location ORDER BY COUNT(*) DESC OFFSET 200 ROWS FETCH NEXT 200 ROWS ONLY)SELECT N'CREATE STATISTICS Location\_Outliers ON dbo.Users(Location) WHERE Location IN (' + STRING\_AGG(Location, N',') + N') WITH FULLSCAN;' AS DynamicSQLFROM OutlierValues; Which gives us a string we can execute, and I’ve highlighted Lithuania just to show that it’s there:

Note that my dynamic SQL is not checking for the existence of the stat and dropping it – if you were going to productize a solution like this, that’s left as an exercise for the reader. You could either drop & create the statistic on a regular basis (like, say, quarterly – the top outliers shouldn’t change that much in a mature database) or create a new filtered state with a date-based name, and then drop the old one. That’s much more work though.

For now, let’s create the statistic and check out its contents:

We now have a bucket dedicated exclusively to Lithuania. Try the Lithuania query filter again, and look at the new actual query plan:

Presto, Lithuania gets accurate estimates, as do any of the other top 200 values.

To see why, right-click on the SELECT operator, click Properties, and go into OptimizerStatsUsage. Both the Location and the Location_Outliers statistics were used when building the query plan’s estimates.

Like I said when I first started talking about this solution above, this solution makes you cringe. It feels dirty, like it’s made out of chewing gum and duct tape. This feels like something that should have a more intuitive solution. For example, over in the free database crowd, Postgres lets you set the number of buckets at the server level with default_statistics_target, and lets you override it with an ALTER TABLE SET STATISTICS command. Postgres lets you pick up to 10,000 outliers – and hell, SQL Server’s filtered statistics solution only gives you another 200 per filtered stat that you create!

At the same time though, the vast majority of tables will never grow large enough to experience this problem. In this blog post, I’m illustrating the problem with the Users table in the most recent Stack Overflow database, and that table has over 22 million rows, with over a decade of activity for a very large web site. Even still, the query we’re talking about doesn’t even have a performance problem!

It’s also important to note that both the 201 buckets problem and the filtered statistics solution have nothing to do with parameter sniffing, trivial optimization, plan reuse, or anything like that. People often get these problems confused because they’re similar, but in this specific example, I’m looking at best-case scenarios for query optimization – this query doesn’t even have parameters, and we’re getting a fresh execution plan each time, specifically designed for Lithuania. (You can try recompile hints to prove to yourself that plan reuse isn’t the issue here, and even with the filtered stats solution, you’d also still have parameter sniffing issues on reusable plans for different locations.)

So would I recommend this solution to solve the above problem? Probably not – but again, like I said, I have to teach you how to solve it in a simple scenario before I move into a more complex, real-world scenario. That one’s coming up in the next Query Exercise where we’ll add in larger tables and more query complexity.

If you want to see even more solutions, check out the comments on the challenge post. Thomas Franz had a particularly interesting one: he created 26 filtered stats, one for each letter of the alphabet, effectively giving him over 5,000 buckets for his statistics!

Hope you enjoyed the challenge! For more exercises, check out the prior Query Exercises posts and catch up on the ones you missed so far.

View Details

I ran a poll over on LinkedIn to find out if people have 100% of their databases under some kind of source control or version control.

I broke the answers up into two sets, developers and non-developers, because I had a hunch that the developers’ answers would be very different than the rest, and indeed they were:

Half (36% + 13% = 49%) of the audience says they have 100% of their database structure & logic under source control – and that’s fantastic for them! I love it. That’s actually better than I expected – however there’s a catch, and I’ll talk about that in a second.

Half (23% + 27% = 50%) says they don’t – and while I’d love for that to be different, I understand that it’s really, really hard. I wish databases like SQL Server just had a “put the source control here” option that would automatically check all changes into a repository, along with who made the change and when, so we had a history. The reality is that today’s databases have no built-in integration with source control, which means you’re gonna have to put in some kind of product and process to make that happen.

Half of the audience is better than none, right? Well, not so fast: remember how I split the audience into developers and non-developers? When I’ve discussed this issue with client teams, the developers have often believed everything was in source control, but the DBAs and sysadmins told a very different story. They’d say, “Uh, well, actually, there have been a lot of changes made to the environment post-deployment, especially by support engineers and vendors, and that stuff hasn’t quite made it back to version control.”

So in reality, even though a high percentage of developers believe they’re doing it right, they’re being let down by other people at the company. Hell, you can even be let down by Microsoft themselves! The ever-funny Sean Alexander pointed out:

Because Azure SQL DB can automatically add and remove indexes in your production database without leaving a bread crumb trail behind to undo its work. Don’t get me wrong, I think that’s a good thing for small to midsize businesses who can’t afford to have a DBA paying attention to every database – but it’s amusing that it works against the goals of source control.

If your databases are 100% in source control, great! I’m so happy for you, and you’re doing it right. You should be really proud of yourself and your team for putting in good practices. It’s now up to you to blog, present, and stream about how other companies can follow in your footsteps. There’s a severe lack of online content around how to do this well with SQL Server and the other Microsoft databases.

If not, take heart: you’re not alone. Even in 2024, lots of your peers are still struggling with the same challenge. To read more about their struggles, check out Mala’s recent roundup of SQL source control blog posts.

View Details

I took your top-voted questions from https://pollgab.com/room/brento, including a few career-oriented ones:

Here’s what we covered:

  • 00:00 Start
  • 01:10 Trushit: You mention in your career internals guide that you focused on high value things for which business are willing to pay. How did you control the temptation of trying to learn everything & focus on just sql server? Btw, looking forward to see you at PASS Summit – fan boy moment.
  • 05:17 Keith: I have a vendor application that is creating over 7,000 connections and my concern is potential Threadpool exhaustion. How do I find out how much memory each connection is taking?
  • 06:58 Trushit: I have been through your fundamental classes. I write T-SQL for reporting & don’t deal with execution plans that often. I am struggling to choose between your precon, Eric’s and Kendra’s performance tuning internals & conquer SQL Server performance monsters. Any thoughts?
  • 08:49 Davros: What’s your opinion of PowerBI and Databricks?
  • 09:31 MustangKirby: I was investigating a customer’s query that seemed stuck. Watching with live query stats showed me that it was hung up on a sort operation. Running sp_whoasactive showed the physical reads were climbing and greater than logical reads. What can cause that?
  • 10:18 Mattia Nocerino: I want to show my developers the problems of abusing NOLOCK but I’m having problems replicating your demo in my database. I’m updating a varchar column and at the same time i’m doing a select count(*), but I don’t see big swings in the result. There are 0 NCI. Any idea?
  • 11:04 Donna Noble: Do you ever see clients with too many SQL cooks in the kitchen (sysadmins)? What misfortunes have you seen from this?
  • 13:15 Vinesh: What’s your opinion of SQL 2022 CETaS functionality to export cold data to Azure storage in Parquet format?
  • 14:28 Dr Disrespect: I’m thinking about changing careers. How hard is it to become a DBA?
  • 15:40 ChompingBIts: I swapped to being a DBA about three years ago now. Your same year of experience over and over comment felt a little too familiar. I’ve been learning to automate more with DBA Tools and finding ways to improve process, but what’s your advice for better experience beyond quiting.
  • 17:14 Kate Stewart: What’s the top issue you run into with locating SQL temp DB on the cloud VM’s ephemeral drive?
  • 18:11 MyTeaGotCold: What’s your favourite way to sabotage a server? Does sp_Blitz catch it?
  • 19:26 WouldLiketoKnow: Is there a way to protect custom SQL from being viewed by others in a Stored Procedure that is being sold? Creating a SP “with encryption” offers some protection but there are still ways to view it. Would storing SP code in a DLL type of file offer any more protection.

View Details

This Query Exercise was very different: I didn’t ask you to solve a particular problem. I pointed out that I’ve heard advice that SELECT MAX is faster than SELECT TOP 1, and that’s not quite true. I asked you to find factors that would cause these two queries to get different execution plans:

SELECT TOP 1 LastAccessDateFROM dbo.UsersORDER BY LastAccessDate DESC;SELECT MAX(LastAccessDate)FROM dbo.Users; In the exercise post, I showed that with a nonclustered rowstore index like this, whose leading column is not LastAccessDate:

CREATE INDEX Location\_LastAccessDateON dbo.Users(Location, LastAccessDate); That would give them different execution plans, leading to TOP 1 being faster because it went parallel, while MAX stayed single-threaded and ran longer.

I tell you what, when I was writing that blog post, the hardest thing by far was not to give away too many answers. I worded that sentence above really, really carefully because right there in that sentence alone, there’s a factor that changes the answers. We could just change something about the environment so that the MAX query goes multi-threaded too (or the TOP 1 query goes single-threaded!)

Cost Threshold for ParallelismContinuing with the above example, let’s change Cost Threshold for Parallelism from the common 50 down to, say, 25:

EXEC sys.sp\_configure N'cost threshold for parallelism', N'25'GORECONFIGUREGO And then run our two queries again. Now, both of them go parallel, as shown in the actual execution plans:

Now both queries qualify for parallelism, and the MAX is faster. On the flip side, if we raise CTFP to a much higher number, like 500, the new execution plans are… wait… hang on a second here…

How does the TOP 1 query still have parallelism? Let’s hover our mouse over the SELECT and examine its Estimated Subtree Cost:

How’s that possible? If my Cost Threshold for Parallelism is 500, how can a query with a cost of 499.193 go parallel? Well, there’s a trick: we’re looking at the estimated cost of the parallel query, not the serial one. To see the cost of the serial query, add an OPTION (MAXDOP 1) hint to it:

SELECT TOP 1 LastAccessDateFROM dbo.UsersORDER BY LastAccessDate DESC OPTION (MAXDOP 1); And we can see that the serial cost is a whopping 977 query bucks:

So that’s why the query goes multi-threaded. Parallelism: it’s a hell of a drug. Alright, let’s reset the playing field before we try other factors:

EXEC sys.sp\_configure N'cost threshold for parallelism', N'50'GORECONFIGUREGODropIndexes;GO Columnstore IndexesThey’re great for aggregate queries like MAX, so let’s slap one on and see how it affects performance:

CREATE NONCLUSTERED COLUMNSTORE INDEX LastAccessDateON dbo.Users(LastAccessDate);GOSELECT TOP 1 LastAccessDateFROM dbo.UsersORDER BY LastAccessDate DESC;SELECT MAX(LastAccessDate)FROM dbo.Users; The actual query plans look similar in the sense that they have the same operator, but the devil’s in the details on this one:

The TOP 1 uses a sort, which sounds bad, because it sounds like it would sort all 8,917,507 rows – especially with that monster arrow coming out of the columnstore index scan operator. However, that arrow doesn’t mean jack, as we explain in the Fundamentals of Columnstore training class.

The bottom line is that the TOP 1 uses 93ms of CPU time and runs in 205ms. The MAX uses 16ms of CPU time and runs in 97ms. The MAX wins both ways here, but it’s not a dramatic win – most folks aren’t going to complain too much about the difference between these two plans.

However, there’s a catch to this comparison: my database happens to be in SQL Server 2016 or newer compatibility mode for this one. Watch what happens when we introduce yet another variable into this experiment…

Compatibility LevelI’ve still got the columnstore index in place, but let’s drop back to 2014 compatibility level:

ALTER DATABASE [StackOverflow] SET COMPATIBILITY\_LEVEL = 120 And then check our new actual query plans:

Sometimes, smaller plans are better. However, not in this case: the wide TOP 1 plan finishes in just 351ms, but the seemingly-simple MAX plan takes a whopping 2.2 seconds to run!

This comparison is also a great reminder that the percentage query costs on plans are absolutely useless and meaningless! I catch people saying, “The bottom query looks better because it’s only 4% of the cost,” but that’s just garbage:

It drives me crazy that Microsoft even includes this junk in query plans in the year 2024. They’re doing a disservice with that number.

What We Learned in This ExerciseI’ve only covered a few variables in the equation that make TOP 1 and MAX perform differently. For more, check out the comments on the Query Exercise post.

Database servers have a butterfly effect: even the slightest change, seemingly unrelated to anything else, can affect query performance all over the place. I’m not saying you have to test everything before you change anything at all – the real world is just too busy and complicated to do that.

That butterfly effect should teach you 3 things:

  1. Just because 2 simple queries produce the same result doesn’t mean they get the same query plan.
  2. Never say “This T-SQL syntax is faster than that other T-SQL syntax,” because there are tons of butterfly effect variables.
  3. Before you give advice on how to write a query, get familiar with the target environment first.

View Details

The short story: SQL Server 2022 finally saw some growth this quarter! Two years after the release, 1 in 10 SQL Servers is finally running the latest version.

The long story: ever wonder how fast people are adopting new versions of SQL Server, or what’s “normal” out there for SQL Server adoption rates? Let’s find out in the summer 2024 version of our SQL ConstantCare® population report.

SQL Server is still the king of the hill with >2x more market share than any other version, but it did drop by one percentage point this month. Here’s how adoption is trending over time, with the most recent data at the right:

SQL Server 2019 still continues to grow while everything else shrinks, with the exception of 2022 treading water:

  • SQL Server 2022: 10%, up from 7% last quarter
  • SQL Server 2019: 48%, holding steady
  • SQL Server 2017: 13%, fairly steady
  • SQL Server 2016: 19%, steady
  • SQL Server 2014: 6%, steady – and is now unsupported as of July
  • SQL Server 2012 & prior: 3%, steady
  • Azure SQL DB and Managed Instances: 1%, steady

Now that 2014 is officially unsupported, it’s interesting to see that the market share of SQL Server 2022 is about the same as the share of unsupported versions. I bet out in the wild, the unsupported version share is even higher just because folks don’t care enough to monitor the oldest zombies. (Plus, SQL ConstantCare doesn’t support pre-2008 versions, which actually still exist – I just got a consulting request for a SQL Server 2005 box this month. And the answer was no.)

If you compare SQL Server 2022’s adoption curve to 2019’s, you’ll notice that SQL Server 2019’s adoption didn’t really take off until 2022 Q3-Q4 – when SQL Server 2022 was released. There might be a few different reasons for that:

  • Maybe people like being 1 version behind, and once 2022 was out, 2019 was the preferred one-behind version
  • Maybe people were waiting for SQL Server 2022, but when the feature list & pricing came out, they decided it wasn’t worth the wait, and moved forward with 2019 instead
  • Maybe they were holding off for the much-anticipated cloud HA/DR integration, but when Microsoft announced that it wouldn’t be included in 2022’s release after all, they decided to move forward with 2019 for now

No matter which one it is (or something else), I’ll be curious to see what happens to 2022’s adoption rate when Microsoft announces the feature list, CPU core & memory limitations, and pricing of the next version of SQL Server. Will that be the thing that finally makes SQL Server 2022 take off?

New SQL ConstantCare® Feature Coming: GamificationBecause we’ve got data for so many servers, consulting clients often ask me, “How big is our database relative to others? Are we using a similar amount of hardware? Are we out of the ordinary compared to our peers?”

Soon, we’re going to give monthly badges to SQL ConstantCare® customers (both free and paid) based on a bunch of rankings. Who has the most data? Who has the largest servers? Who has the longest uptime? And they won’t just be badges of pride – there are also badges of shame, like whose servers have the most problems, or who’s muted/ignored the most recommendations.

I’ll be blogging about the various badges over the coming weeks, explaining how the rankings are calculated, where the data comes from, and what the typical leaderboard looks like so that you get a rough idea of what it looks like at the top – and at the bottom.

If there’s a metric that you’d like to see rankings for, feel free to add it in the comments! We just might build a badge for it.

View Details

Over the last week, I’ve been working on putting together a Postgres version of the Stack Overflow database, just like the SQL Server one that I’ve distributed for almost a decade now.

I’ve worked with Microsoft SQL Server for so long that I just kinda took backups for granted. We run a backup command, and SQL Server:

  1. Logs activity to the transaction log while the backup is running
  2. Reads the exact contents of the database files, and writes them out to a backup file
  3. When it’s done, it also includes the transaction log changes so that it can use the combination of the data files, plus the transactions that happened during the backup itself, to get a single point in time version of the database files

All without stopping transactions or closing the data files. It’s pretty nifty, and it works really well. The good part is that it’s very efficient at backing up the entire database, and restoring the entire database to a single point in time.

The drawback is that it’s impossible to restore a single object from backup, by itself. Oh sure, we’ve complained about it for years, and it’s the #2 top voted feature request, but it doesn’t seem to be happening anytime soon. We’ve learned to work around that by restoring the entire database somewhere else, and then extracting just the data we need.

PostgreSQL Backups are Totally Different.One of the gotchas of Postgres is that there are a million different ways to accomplish any task. You could stop the database service and get file-level backups, but of course that’s a bad idea for production databases. You could install extensions like Barman to automate backups for you, and in many cases that’s a great idea for production databases. However, we’re going to focus on the built-in way that most shops start with.

When you back up a database with pg_dump, it actually generates a text file with statements like CREATE TABLE and INSERT that reconstruct the data from scratch.

I’ll give you a moment to re-read that sentence.

At first, you’re going to be horrified, but give it a second and open your mind.

Sure, there are drawbacks: if you work with databases over a few hundred megabytes in size, it probably horrifies you to think about a text file that large. No worries: you can tell pg_dump to compress (zip) the output into a custom file format as it goes. Another drawback is that there’s no such thing as combining transaction log backups with this – if you want to get point-in-time recovery, you’re going to need a better solution than pg_dump.

However, pg_dump has some pretty intriguing advantages – for starters, table-level restores. The pg_restore documentation page has all kinds of switches for just restoring one table, or only restoring the data (not the schema), or just restoring specific indexes, or more.

Speaking of indexes, get a load of this: because pg_dump is only backing up the data, indexes don’t bloat your backup files. You could have 50 indexes on a table, but that index data itself isn’t getting backed up – only the index definition, aka the CREATE INDEX statement! At restore time, pg_restore reads the backup file, runs insert commands to load the data, and then when it’s all there, runs the CREATE INDEX statements necessary to re-create your indexes. Your database can be partially online while the indexes are re-created. (Is this restore strategy going to be faster? Probably not, and I’m not going to test it, but it’s wild to know.)

But here’s the part that’s really going to blow your mind: since the dump file is just a list of commands, it’s technically possible to restore a Postgres database back to an earlier version. Take a plain-text backup (or convert the existing one to plain-text format), and then execute the commands, looking for any errors caused by newer engine features. Edit the backup file to remove the unavailable features in your older version, and then try again.

Which Approach Is Better?Microsoft’s approach focuses on backing up (and restoring) the exact data file contents at extremely high speed, shoving the data out without concern for its contents. Properly tuned, it’s fast as hell. I’ve had clients who regularly backed up and restored 1-5TB databases in just 5-20 minutes. That’s useful when you’ve got very short SLAs, but not shared storage.

Microsoft’s integration with the transaction log also means that the full backup is very extensible. You can integrate it with log backups, or use it to seed transaction log shipping, database mirroring, or Always On Availability Groups. There’s just one backup approach in SQL Server, but it has all kinds of flexibility that Microsoft has built up over the decades.

On the other hand, there are a bunch of different ways to back up Postgres databases. If you choose the pg_dump approach, it also lends itself to all kinds of creative use cases right out of the box. The more I played with it, the more amused I was at its capabilities. For example, backing up data from AWS Aurora Postgres and restoring it to my local Postgres instance was a no-brainer. The fact that one was a platform-as-a-service database in the cloud, and the other was an on-premises database, just simply didn’t matter – something Azure SQL DB just can’t pull off, even though Microsoft manages the whole code stack.

Microsoft has just one backup tool, and it works really well – as long as you don’t need to do something unusual, like restore a single table or downgrade versions. Postgres has lots of backup tools that have more flexibility and power overall – buuuut, it’s up to you to pick the right one and then configure it in a way that supports your RPO/RTO.

View Details

I don’t get it. I’ve given this feature one chance after another, and every time, it takes a smoke break rather than showing up for work.

The latest instance involved the recent Query Exercise where you were challenged to fix a computed column’s performance. In the comments, some folks noted that performance of the query was actually great on old compat levels, like SQL Server 2008, and that it only sucked on newer compat levels like 2016 and later.

That would be the perfect use case for Automatic Tuning, I thought to myself! I’ve said this so many times over the last five years, but I’m an endlessly hopeful optimist, as anyone who knows me well would never say, so I gave it another chance.

We’ll set up the same user-defined function and computed column described in that blog post:

USE StackOverflow;GOCREATE OR ALTER FUNCTION dbo.IsValidUrl (@Url NVARCHAR(MAX))RETURNS BITASBEGIN DECLARE @Result BIT = 0 -- Regex pattern for a valid URL -- This pattern covers: -- - Scheme (http, https, ftp) -- - Optional username:password -- - Domain name or IP address -- - Optional port -- - Optional path -- - Optional query string -- - Optional fragment IF @Url LIKE 'http://%' OR @Url LIKE 'https://%' OR @Url LIKE 'ftp://%' BEGIN IF @Url LIKE '%://[A-Za-z0-9.-]%.%' -- Check for domain/IP after scheme AND @Url NOT LIKE '% %' -- No spaces allowed in URL AND @Url LIKE '%.[A-Za-z]%' -- Ensure there's a period in domain/IP part AND @Url LIKE '%/%' -- Ensure there's at least one slash after the domain AND @Url LIKE '%[A-Za-z0-9/\_-]%' -- Ensure there's at least one valid character in the path BEGIN SET @Result = 1 END END RETURN @ResultENDGOALTER TABLE dbo.Users ADD IsValidUrlAS dbo.IsValidUrl(WebsiteUrl);GO We’ll set up an index on the Reputation column, and a stored procedure that’ll benefit from using that index:

CREATE INDEX Reputation ON dbo.Users(Reputation);GOCREATE OR ALTER PROC dbo.GetTopUsers ASBEGINSELECT TOP 200 *FROM dbo.UsersWHERE IsValidUrl = 1ORDER BY Reputation DESC;ENDGO We’ll put our database in old-school compat level, and turn on Query Store to start collecting data at a frantically quick pace:

ALTER DATABASE CURRENT SET COMPATIBILITY\_LEVEL = 110 /* 2012 */GOALTER DATABASE SCOPED CONFIGURATION SET LEGACY\_CARDINALITY\_ESTIMATION = OFF;GOALTER DATABASE CURRENT SET QUERY\_STORE = ONGOALTER DATABASE CURRENT SET QUERY\_STORE (OPERATION\_MODE = READ\_WRITE, DATA\_FLUSH\_INTERVAL\_SECONDS = 60, INTERVAL\_LENGTH\_MINUTES = 1)GOALTER DATABASE CURRENT SET QUERY\_STORE CLEAR;GO We’ll run the query a few times, noting that it runs blazing fast, sub-second:

EXEC dbo.GetTopUsers;GO 5 And check Query Store’s Top Resource Consuming Queries report to show that the plan is getting captured:

Now, let’s “upgrade” our SQL Server to the latest and “greatest” compatibility level, and turn on Automatic Tuning so that it’ll “automatically” “fix” any query plans that have gotten worse:

ALTER DATABASE CURRENT SET COMPATIBILITY\_LEVEL = 160 /* 2022 */GOALTER DATABASE CURRENTSET AUTOMATIC\_TUNING ( FORCE\_LAST\_GOOD\_PLAN = ON ); GO Now, when we go to run our query again, it takes >30 seconds to run, burning CPU the entire time – and zee Automatic Tuning, it does nothing. Query Store shows that there’s a new plan, and that the runtime is way, way worse:

But sys.dm_db_tuning_recommendations shows nothing, even though Query Store is on and so is “Automatic” “Tuning”:

To see it in inaction, here’s a live stream:

I don’t get it. I’ve given this feature so many chances, and it’s never kicked in for me at the right times. I’m guessing I’m missing some secret set of steps I need to take, but whatever it is, it’s beyond me. Maybe you can get it to work in this scenario, and share your magic? Now’s your chance to make me look like a fool.

Well, I mean, like even more of a fool.

View Details

Is your company hiring for a database position as of August 2024? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

What a comfy morning to sit down with a breakfast margarita and tackle your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:36 DBA_Mufasa: When we restore a DB from a prod source to a different server, does the DB come with the index usage stats from the original source server or do they get reset on the destination server once the DB is restored. Trying to figure out if people are using a daily restored DB in Dev.
  • 01:44 Trushit: I have a stored procedure that uses XML path to create the XML tree. I want to store this in variable. However, stored procedure returns a column with a link to XML tree. Only when I click on the link, full tree is visible. Any ideas how to access the entire XML tree?
  • 02:43 MyTeaGotCold: I like your arguments for always setting fill factor to 100. But do the same arguments mean that I should default to using DATA_COMPRESSION = PAGE on my rowstore indexes?
  • 04:02 Rose Noble: You’ve mentioned your aversion to linked server queries. Are linked server sprocs acceptable?
  • 04:49 Genuinely Curious: We’re using Standard Edition at the moment. When should I start thinking about Enterprise Edition?
  • 05:27 Yord: What are the top issues you see for rolling out read only AG replicas?
  • 06:32 Pink Pony: What’s your opinion on db setting “auto update statistics asynchronously”? Should we change value to True?
  • 07:49 Miles: Hi Brent, When we’ve resource intensive queries, which ones one should focus on first? high I/O or high CPU or head blocker queries or parallelism or based on waits or user complained queries? Please suggest? Whats the approach one should follow?
  • 08:44 Genuinely Curious: If Azure SQL DB Managed Instances are as good as SQL Server, but require less maintenance, why would people keep using SQL Server?
  • 10:51 TJ: Redo thread on secondary replica tends to get blocked by SELECT queries which in turn block other queries. We have to currently kill the select queries to resolve blocking. Is this the correct way to handle this situation?
  • 12:26 SQL_Stormlight: A friend needs to design a DR solution across datacenters for 2300+ dbs. It /seems/ like the best option is a FCI but how do they deal with the shared storage? Would SAN replication get them further than clustering or are the two used in tandem?

View Details

The EightKB conference is a free event that focuses on SQL Server internals.

You can get the session details and register for the August 8th event at eightkb.online. The session lineup is below, each link being a calendar invite just so you can block out your calendar:

  • Opening Welcome
  • X-Raying Schema Operations: Adding and Removing Columns by Claudio Silva
  • Azure SQL Database Business Continuity by Jes Schultz
  • Mining Statistics for Data insights by Deborah Melkin
  • Navigating High Availability Challenges and Preventative Strategies for “Split Brain” by Amy Abel
  • Black Box No More: LLM Internals by Argenis Fernandez

To see the full session abstracts and register, head to eightkb.online.

View Details

Every year, Stack Overflow runs a developer survey about technology, work, community, and more. This year’s results include 65,437 responses from developers around the world.

The results are biased towards the kinds of developers who use Stack Overflow – 76% of the respondents reported that they have a Stack Overflow account. I would guess that it’s nowhere near a perfect picture of all developers worldwide, but let’s just focus on the fact that it does represent how over 65,000 developers feel – and that alone is useful enough to give you a picture of what’s happening in at least a lot of shops worldwide.

The most-used databases were PostgreSQL, MySQL, SQLite, and Microsoft SQL Server, in that order:

When Jeff Atwood and Joel Spolsky first started Stack Overflow, Jeff did a lot of evangelization work for it, and Jeff’s audience was heavily biased towards .NET development. I would imagine that’s part of why SQL Server is by far the highest paid database in the list (as opposed to open source.)

I have a total blind spot around SQLite, but often on my TikTok videos when the discussion of licensing costs comes up, some commenters will ask why everyone in the world doesn’t use SQLite. I’m sure there are a lot of apps worldwide that simply don’t need a database server, only a small local relational storage, and I can understand why those developers would have a similar blind spot about what it’s like to handle concurrent load in an enterprise-wide ERP app or e-commerce store.

The next chart, admired-vs-desired, doesn’t make sense to me and I don’t trust the numbers:

From what I can tell, the blue scores indicate how much the respondents have worked with the database in the last year, and red scores indicate how much they want to work with it next year? I’m pretty confused by this one. Are the red scores exclusive to only the people who actually worked with the technology this year – meaning, out of the 15.4% of the audience that worked with SQL Server in the past year, 54.5% of them want to work with it next year?

And why don’t these numbers come anywhere near agreeing with the prior question? The prior question says 25.3% of the audience used it last year, but the admired-vs-desired question says only 15.4% did? I’m so lost. At first I thought this question is taking about “extensive” development work, whereas the first one might just be ANY database work – but the numbers don’t make sense there either, because Supabase scored 4% on the first question (any work), but 5.9% on this question (extensive work.) Both questions use the term “extensive.” I’m lost.

So yeah, I just discarded that question and didn’t bother to think about the results. It doesn’t make sense, so I don’t trust it.

There was also a question about which cloud provider folks used, and AWS dominated the market:

That’s been my experience too – the vast, vast majority of my cloud clients are on AWS – but I’m mentioning it here because I know that Azure users really seem to believe Azure’s the only game in town. When I talk to Microsoft MVPs, they seem dumbfounded that companies are actually using AWS extensively, and they also seem surprised that Microsoft is competing with Google for second place. (Google’s been throwing a lot of discounted/free compute power at prospective clients to win them over.)

There’s a lot more stuff in the overall results, especially the workplace trends section that talks about employment status, hybrid/remote/in-office, and salary. When you’re looking at each workplace graph, make sure to click on the geographic filter at the top of that graph so the numbers will be more meaningful to you, based on where you’re located.

View Details

While taking a dip in Cabo, I went through your top-voted questions from https://pollgab.com/room/brento.

https://www.youtube.com/watch?v=OaHImrIMM6Y

Here’s what we covered:

  • 00:00 Start
  • 01:00 OpportunityKnocking: What are your thoughts on when to implement a NoSQL strategy over traditional RDBMS for large enterprise-wide database platform solutions? I see scalability advantages in using NoSQL but do you see this becoming more of a preferred go-to solution for organizations over time?
  • 01:57 SwissDBA: In a table with 8M rows, 2 GB data + 4GB indexes, Clustered ix on a GUID column. INSERTs are slow bc SQL has to squeeze them in between existing rows. I would switch the clustered ix to a new IDENTITY column, so new records can be added at the end of the tbl. How would you do it?
  • 03:01 MyTeaGotCold: You recently said that your Hekaton clients are trying to get off. The faults of Hekaton are well-known, so what changed between when they started using it and now?
  • 03:54 Tim Rogers: 90 TB database in AWS, all data active. Tables partitioned across 100 filegroups (4 files each) for ease of index maintenance. Would like to consolidate to a single “data” filegroup with ~100 files, because we don’t do anything that benefits from multiple filegroups. Thoughts?
  • 06:30 Kevin M: Would like to learn Amazon Aurora despite current company not using Amazon stack. What’s the best / cheapest way to learn Amazon Aurora?
  • 07:47 SadButTrue: Hey Brent! Who’s the “Brento” in Postgres community?
  • 08:26 RadekG: When was the last time that you faced a query so poorly written that you had to have a drink before fixing it? What was so bad about it?
  • 11:19 Jökull: What are the top issues you see when storing / searching XML/JSON in SQL Server?

View Details

In last week’s Query Exercise, we added a user-defined function to the Users table to check whether their WebsiteUrl was valid or not. I noted that even with an index on Reputation, SQL Server 2022 simply ignored the index, did a table scan, and spent 2 minutes of time calling the user-defined function on a row-by-row basis.

First off, a disclaimer: I didn’t write that exercise with a goal of showing the difference between old & new SQL Server versions, between old & new compatibility levels. However, several folks in the comments said, “Hey, I’m on an older version, on an older compatibility level, and the query is blazing fast already. What do I need to fix?” That’s a good reminder of what work you need to do before you go live on SQL Server 2022 (or any new version.) Moving on.

One Fix: Persisting the Computed ColumnOne way to fix it is to drop the computed column, then create it again with the PERSISTED keyword:

ALTER TABLE dbo.Users DROP COLUMN IsValidUrl;GOALTER TABLE dbo.Users ADD IsValidUrlAS dbo.IsValidUrl(WebsiteUrl) PERSISTED;GO That way, SQL Server computes each row’s contents just once, and then persists it in the table itself, instead of running the function every time we query it. By executing the above code, we get:

Wait, what? As a reminder, here’s the contents of our function:

CREATE OR ALTER FUNCTION dbo.IsValidUrl (@Url NVARCHAR(MAX))RETURNS BITASBEGIN DECLARE @Result BIT = 0 -- Regex pattern for a valid URL -- This pattern covers: -- - Scheme (http, https, ftp) -- - Optional username:password -- - Domain name or IP address -- - Optional port -- - Optional path -- - Optional query string -- - Optional fragment IF @Url LIKE 'http://%' OR @Url LIKE 'https://%' OR @Url LIKE 'ftp://%' BEGIN IF @Url LIKE '%://[A-Za-z0-9.-]%.%' -- Check for domain/IP after scheme AND @Url NOT LIKE '% %' -- No spaces allowed in URL AND @Url LIKE '%.[A-Za-z]%' -- Ensure there's a period in domain/IP part AND @Url LIKE '%/%' -- Ensure there's at least one slash after the domain AND @Url LIKE '%[A-Za-z0-9/\_-]%' -- Ensure there's at least one valid character in the path BEGIN SET @Result = 1 END END RETURN @ResultENDGO HOW THE CELKO IS THAT NOT DETERMINISTIC? What, does string comparison change from time to time? Books Online’s article on determinism says “All of the string built-in functions are deterministic,” but I’m guessing this has something to do with a possibly changing collation, and I couldn’t care less about digging further. That’s left as an exercise for the reader. Moving on.

An Actual Quick Fix: WITH SCHEMABINDINGI used to hear people say, “You should put WITH SCHEMABINDING on your scalar functions and they’ll go faster.” Every single time I tried it, it made no difference whatsoever.

Until…last week! In the comments, Ag suggested to add that hint to the function, and it ran rapidly! We’ll remove the existing column, tweak the function – the only change is WITH SCHEMABINDING – and then add it back in:

ALTER TABLE dbo.Users DROP COLUMN IsValidUrl;GOCREATE OR ALTER FUNCTION dbo.IsValidUrl (@Url NVARCHAR(MAX))RETURNS BIT WITH SCHEMABINDINGASBEGIN DECLARE @Result BIT = 0 -- Regex pattern for a valid URL -- This pattern covers: -- - Scheme (http, https, ftp) -- - Optional username:password -- - Domain name or IP address -- - Optional port -- - Optional path -- - Optional query string -- - Optional fragment IF @Url LIKE 'http://%' OR @Url LIKE 'https://%' OR @Url LIKE 'ftp://%' BEGIN IF @Url LIKE '%://[A-Za-z0-9.-]%.%' -- Check for domain/IP after scheme AND @Url NOT LIKE '% %' -- No spaces allowed in URL AND @Url LIKE '%.[A-Za-z]%' -- Ensure there's a period in domain/IP part AND @Url LIKE '%/%' -- Ensure there's at least one slash after the domain AND @Url LIKE '%[A-Za-z0-9/\_-]%' -- Ensure there's at least one valid character in the path BEGIN SET @Result = 1 END END RETURN @ResultENDGOALTER TABLE dbo.Users ADD IsValidUrlAS dbo.IsValidUrl(WebsiteUrl); Then rerun our query without changes:

SELECT TOP 200 *FROM dbo.UsersWHERE IsValidUrl = 1ORDER BY Reputation DESC; Even on a large Stack Overflow database, the query runs in milliseconds and produces a great execution plan:

SQL Server uses the index only only reads a few hundred rows before the work is done. Sure, there’s no parallelism in the query, and the plan properties report that “TSQLUserDefinedFunctionsNotParallelizable”, but who cares? The query’s so fast, even with millions of candidate rows, that it doesn’t matter. Good enough, ship it.

My Old Faithful Fix: A TriggerI know. I know, the word makes you break out in itchy hives, but triggers are a great way to quickly replace computed columns.

Let’s drop the existing computed column, add a new “real” column, configure the trigger to populate it going forward, and then backfill it to set up the existing data:

ALTER TABLE dbo.Users DROP COLUMN IsValidUrl;GOALTER TABLE dbo.Users ADD IsValidUrl BIT;GOCREATE OR ALTER TRIGGER Users\_IsValidUrl ON dbo.UsersAFTER INSERT, UPDATEAS BEGINUPDATE uSET IsValidUrl = dbo.IsValidUrl(u.WebsiteUrl)FROM dbo.Users uINNER JOIN inserted i ON u.Id = i.Id;END; GO UPDATE dbo.UsersSET WebsiteUrl = WebsiteUrl;GO The first few statements will run instantly (assuming nobody else is locking the Users table), but the last statement will take a minute since it’s actually adding a new value to every row in the Users table, AND it’s calling a scalar function on every row. You could make that faster with set-based operations, but more on that in a minute.

After that, run the query we’ve been trying to tune:

SELECT TOP 200 *FROM dbo.UsersWHERE IsValidUrl = 1ORDER BY Reputation DESC; It runs in a couple milliseconds (down from a minute) and uses the Reputation index, as the execution plan shows:

I like the trigger solution for a few reasons:

  • It keeps the function’s logic as-is, which can be helpful in situations where the logic is really complex, time-tested, and labor-intensive to rewrite.
  • It can be implemented really quickly.
  • Queries against the table can now go parallel if they need to.

But there’s a drawback: the trigger’s still getting called on every insert and update. If the workload involves batch jobs to load or modify the table, that’s going to be problematic because they’re going to slow down. Those modifications didn’t call the computed column’s function before since they most likely weren’t reading that column. If our workload includes batch jobs, we’re gonna need a faster solution. We’ll clean up after ourselves before trying the next one:

DROP TRIGGER [dbo].[Users\_IsValidUrl]GOALTER TABLE dbo.Users DROP COLUMN IsValidUrl;GO Rewriting the FunctionMost of the time when you hear database people complaining about functions, they’re complaining about user-defined functions. For example, in this case, we can get a dramatic performance improvement if we forklift the business logic out of the user-defined function and inline it directly into the table’s definition itself. Here’s the end result:

ALTER TABLE dbo.Users ADD IsValidUrlAS CASE WHEN (WebsiteUrl LIKE 'http://%' OR WebsiteUrl LIKE 'https://%' OR WebsiteUrl LIKE 'ftp://%')AND (WebsiteUrl LIKE '%://[A-Za-z0-9.-]%.%' -- Check for domain/IP after scheme AND WebsiteUrl NOT LIKE '% %' -- No spaces allowed in URL AND WebsiteUrl LIKE '%.[A-Za-z]%' -- Ensure there's a period in domain/IP part AND WebsiteUrl LIKE '%/%' -- Ensure there's at least one slash after the domain AND WebsiteUrl LIKE '%[A-Za-z0-9/\_-]%' -- Ensure there's at least one valid character in the path ) THEN 1 ELSE 0 END;GO Note that the logic isn’t identical because I had to tweak it: instead of using IF, I used CASE statements, and there’s no @Url parameter anymore because we’re referencing the WebsiteUrl column directly. The more complex your user-defined function is, the harder work this is going to be. To learn how to do these kinds of rewrites, check out Microsoft’s PDF whitepaper on Froid, the inline function technology they added in SQL Server 2019. That paper gives several specific examples of language to use when rewriting functions to go inline, which is quite nice of them.

Now, when the SELECT runs, the plan looks big:

And while the estimates aren’t good, the plan shape is fine, it uses the index, and it runs in milliseconds.

Eagle-eyed readers will note that I did not use the PERSISTED keyword in the above example. If you add that, the resulting plan shape looks even better because the function doesn’t have to run at read time:

And the query finishes in even fewer milliseconds. However, executing the ALTER TABLE with the PERSISTED keyword will lock & rewrite the table, so it’s a question of whether your workload can tolerate that outage. You could always start with the non-persisted version to quickly make the pain go away, and then later if you still need more performance, take an outage to drop the non-persisted computed column (which will be instantaneous) and then add the persisted one (which will be the opposite of instantaneous.)

Hope you enjoyed the challenge! For more exercises, check out the prior Query Exercises posts and catch up on the ones you missed so far.

View Details

I give away a lot of stuff in various places on the internet: videos, scripts, the new free tier of SQL ConstantCare®, and I’ve got more tricks coming soon.

But until now, it’s been kind of a hassle because they’ve been scattered all over the place, not in a sensible order to help you onboard gradually.

So now, my shop page has a simplified set of bundles, starting with an absolutely free membership:

Free$0per year* SQL ConstantCare® with Health Monitoring * Introductory Classes: * How to Think Like the Engine * How I Use the First Responder Kit

Sign upFundamentals$995per year* SQL ConstantCare® with Health & Performance Monitoring * Fundamentals Classes * Purchased Individually: $1,542

Sign upMastering$1,995per year* Everything in * Fundamentals, plus: * Mastering Classes * The Consultant Toolkit * Purchased Individually: $3,617

Sign upThis new Free Stuff bundle will make it easier for me to put my free resources all in one place, in a more logical order. Folks can track their progress through the resources, checking chapters off as they work through ’em.

I updated my free How to Think Like the Engine class this week with a new recording using the 50GB Stack Overflow 2013 database. This way, people can get started on the exact same database that I use throughout the Fundamentals classes, making it a little easier to get onboard.

I’ve also made my How I Use the First Responder Kit class completely free. I’ve always believed that if I can solve your problems for free, then I wanna be the person who does that, so I might as well put you in the best position possible to use the FRK scripts.

For the pros, I’ve also added a new Mentoring tier.The Mentoring tier includes everything in Mastering, plus:

  • Quarterly 30-minute Zoom calls with just you & me, talking about whatever database pains you’re up against
  • Monthly server review emails from me – I go through your SQL ConstantCare® data, look at the server having the most performance issues (or the one you request), and give you my thoughts about what steps to take to improve performance

That tier is $3,495/year for 1 person. It’s designed for folks who don’t quite need my full 2-day hands-on SQL Critical Care® engagement, and just want periodic feedback from time to time.

Frequently Asked Questions“If I have an existing subscription, does this change anything?” Nope! Not at all. You can continue with your current one, or if you’d like to change something, you can cancel your existing subscription and pick up one of these instead. (We don’t have the ability to upgrade in place.)

“Can I still buy classes individually?” Yep! Just keep scrolling down on the shop page. The vast, vast majority of my buyers pick up the bundles so I keep those at the top.

“Can I buy the mentoring without training?” No, because often my advice includes a link to a specific training module to explain the issue you’re facing.

“Can I get group discounts?” Yes, if you’re enrolling 5 or more people in the same membership tier, email us at Help@BrentOzar.com with the tier you want, and the list of email addresses to register, and we’ll get you a quote.

For other questions, feel free to drop ’em in the comments or contact me.

View Details

Last night, two major IT disasters struck:

  • Microsoft Azure’s Central region went down for about 4 hours. The official post-mortem isn’t out yet, but rumor has it that while decommissioning legacy storage services, the product group deleted the wrong thing.
  • Crowdstrike pushed a bad update, leading to blue screens of death on Windows systems worldwide, affecting banking, healthcare, airlines, and more.

If you were affected by one of those outages, you have my warmest virtual hug. At times like this, the stress level can be really tough, and I hope you can take care of yourself. Remember that your own self-worth is not determined by the IT solutions you work on.

If you weren’t affected by one of those outages, it’s a good time to spend an hour writing up a few things:

  • Which of our production services are hosted entirely in a single region, availability zone, or data center?
  • How are we monitoring the status of that single point of failure? If there’s a widespread outage like that, how much time are we going to waste troubleshooting our own services when there’s a bigger problem?
  • When our single-region or single-AZ production services go down, what users/customers would be affected?
  • How will we communicate the outage to those affected users? Can we write that notification ahead of time so that it’s ready to go quickly in the event of the next disaster like this?
  • How much would it cost us (monthly or annually) to add in a second region or availability zone for protection from these kinds of incidents?

Summarize that, pass it up to your manager in writing, and it’ll help them have discussions this morning with their managers and executives. Today, a lot of business folks are going to be asking questions, and having these answers will help get you the resources you want.

(Or, it’ll help you feel more comfortable that the business understands the risks of putting all their eggs in a single basket, and that when that basket breaks, it’s not your fault. You warned ’em, and they chose not to spend the money to double-up on baskets.)

View Details

On a pleasantly mild morning, I sat down on the patio and took your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:56 MyTeaGotCold: When going in to a database blind, do you worry at all about its compatibility level? I see a lot of unloved databases that are still on 2008’s level, but the tiny potential for breaking changes makes me scared to touch it.
  • 02:01 Vishnu: For boxed SQL, Is it ok for users to create SQL agent jobs that run periodic business logic and/or email end users?
  • 02:59 Karthik: What’s your opinion of live query plan viewing in SQL Sentry Plan Explorer?
  • 03:26 Jessica : I am DBA who previously managed dozens of Azure VMs running SQL Server AGs. After a layoff and new job I’m now managing 1 prod Azure SQL db. Any tips for someone making a transition like this? Every day I’m finding features that I no longer have access to and minimal monitoring.
  • 04:29 Hong Kong Phoey: Currently, when we see a non-clustered index on a given multi-tenant SQL table, we may or may not know why it’s there, who created it, when it was created or which app needs it. What’s the recommended change control process for answering these questions?
  • 05:35 Kevin M: What’s the best place to go for commercial PostgreSQL training?
  • 06:02 NotCloseEnoughToRetirementToStopLearning : Hi Brent Inheriting a VLDB (50Tb) any recommended articles or trainings for working with something this size?
  • 07:05 Mike: Hi Brent! When migrating from SQL Server 2017 to SQL Managed Instance, on MI databases after restore become FORCE_LAST_GOOD_PLAN = ON (On 2017, it was OFF). Do you recommend leaving it ON, or should we turn it OFF on initial stages ?
  • 08:27 Venkat: What’s the most common detrimental complacency you see with SQL dbas?
  • 09:13 Mattia: Can a big analytical query that does many logical reads (compared to the SQL Server RAM) give SQL Server Plan cache amnesia? Or is the Buffer Pool completely separated from the Plan Cache?
  • 09:48 Nickelton: Is it possible to forward select queries to AG secondary replica without changing application side? (connection string etc.) For example running code from SSMS or for legacy applications.
  • 11:22 WB_DBA: My friend suggests creating all indexes on a test database since it mirrors the production database. Is this a good approach?

View Details

Take any size of the Stack Overflow database and check out the WebsiteUrl column of the Users table:

Sometimes it’s null, sometimes it’s an empty string, sometimes it’s populated but the URL isn’t valid.

Let’s say that along the way, someone decided to ask ChatGPT to build a function to check for valid website URLs, and then used that code to add a new IsValidUrl column to the Users table (and yes, this is inspired by a real-life client example, hahaha):

CREATE OR ALTER FUNCTION dbo.IsValidUrl (@Url NVARCHAR(MAX))RETURNS BITASBEGIN DECLARE @Result BIT = 0 -- Regex pattern for a valid URL -- This pattern covers: -- - Scheme (http, https, ftp) -- - Optional username:password -- - Domain name or IP address -- - Optional port -- - Optional path -- - Optional query string -- - Optional fragment IF @Url LIKE 'http://%' OR @Url LIKE 'https://%' OR @Url LIKE 'ftp://%' BEGIN IF @Url LIKE '%://[A-Za-z0-9.-]%.%' -- Check for domain/IP after scheme AND @Url NOT LIKE '% %' -- No spaces allowed in URL AND @Url LIKE '%.[A-Za-z]%' -- Ensure there's a period in domain/IP part AND @Url LIKE '%/%' -- Ensure there's at least one slash after the domain AND @Url LIKE '%[A-Za-z0-9/\_-]%' -- Ensure there's at least one valid character in the path BEGIN SET @Result = 1 END END RETURN @ResultENDGOALTER TABLE dbo.Users ADD IsValidUrlAS dbo.IsValidUrl(WebsiteUrl); The user-defined function isn’t accurate, for starters – it’s letting things through that aren’t valid URLs, and stopping things that are actually valid – but let’s set that aside for a second.

What happens when we try to get the top users by reputation? To give SQL Server the best shot, I’m using SQL Server 2022, with the database in 2022 compatibility level, with an index on Reputation:

CREATE INDEX Reputation ON dbo.Users(Reputation);SET STATISTICS TIME, IO ON;GOSELECT TOP 200 *FROM dbo.UsersWHERE IsValidUrl = 1ORDER BY Reputation DESC; The actual query plan is deceivingly simple, despite its terrible performance that takes about a minute to run:

Crouching Tiger, Hidden ScalarWHERE IS YOUR FUNCTION INLINING GOD NOW? I could make movie jokes about this all day. Anyhoo, the plan ignored the Reputation index, did a 2-second table scan, and spent nearly a minute doing the scalar function and the filtering.

To add insult to injury, if you’re going to do 1 minute of CPU work, it sure would help to parallelize that query across multiple cores – but that query can’t get parallelism, as explained in the plan properties:

SpacesNotAvailableEitherYour Query Exercise this week isn’t to fix the accuracy of the function – you can leave it as inaccurate if you like. Your challenge is to have the exact same query run in less than a second. Our goal is to avoid changing application code, and to get a very fast fix in place without blaming the developers. You’re the data professional: be professional.

Put your queries in a Github Gist, and include that link in your comments. Check out the solutions from other folks, and compare and contrast your work. I’ll check back next week with my thoughts. Have fun!

Update: please read the post in its entirety, and follow the instructions. Please don’t just throw ideas in there or half-formed T-SQL. For someone to test your work, they need to see your exact work. C’mon, folks – this isn’t a major project, just a single function. Be fair to people on the other side of the screen.

View Details

Stack Overflow publishes a data dump with all user-contributed content, and it’s a fun set of data to use for demos. I took the 2024-April data dump, and imported it into a Microsoft SQL Server database.

It’s an 31GB torrent (magnet) that expands to a ~202GB database. I used Microsoft SQL Server 2016, so you can attach this to anything 2016 or newer. If that’s too big, no worries – for smaller versions and past versions, check out my How to Download the Stack Overflow Database page.

Some quick facts about this latest version:

  • Badges: 51,289,973 rows; 4.7GB
  • Comments: 90,380,323 rows; 26.1GB
  • Posts: 59,819,048 rows; 162.8GB; 32.7GB LOB – this is where you’ll find questions & answers
  • Users: 22,484,235 rows; 2.6GB; 12.5MB LOB
  • Votes: 238,984,011 rows; 5.9GB – a fun candidate for columnstore demos

As with the source data, this database is licensed under cc-by-sa-4.0: https://creativecommons.org/licenses/by-sa/4.0/ And to be very clear, this is not my data. The data and the below licensing explanation comes from the Stack Overflow Data Dump’s page:


But our cc-by-sa 4.0 licensing, while intentionally permissive, does require attribution:

Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). Specifically the attribution requirements are as follows:

  1. Visually display or otherwise indicate the source of the content as coming from the Stack Exchange Network. This requirement is satisfied with a discreet text blurb, or some other unobtrusive but clear visual indication.
  2. Ensure that any Internet use of the content includes a hyperlink directly to the original question on the source site on the Network (e.g., http://stackoverflow.com/questions/12345)
  3. Visually display or otherwise clearly indicate the author names for every question and answer used
  4. Ensure that any Internet use of the content includes a hyperlink for each author name directly back to his or her user profile page on the source site on the Network (e.g., http://stackoverflow.com/users/12345/username), directly to the Stack Exchange domain, in standard HTML (i.e. not through a Tinyurl or other such indirect hyperlink, form of obfuscation or redirection), without any “nofollow” command or any other such means of avoiding detection by search engines, and visible even with JavaScript disabled.

This will probably be the last database update.Prosus (a tech investment company) acquired Stack Overflow a few years ago for $1.8 billion. When a company’s founders sell their baby for money:

  • The new owners usually want to make a profit on their large investment, and
  • The new owners rarely share the same goals as the original founders, and
  • Sometimes the new owners spent way, way too much (hi, Elon) and are forced to make tough decisions to make their debt payments and keep the company afloat

So now Prosus wants to earn their $1,800,000,000 back, and they’re looking at the actual product they bought. StackOverflow.com has 3 components[1]:

  1. An online app that gives you good-enough answers, quickly
  2. The existing past answers already contributed by the community
  3. The potential of future answers continuing to go into the platform

Can Prosus compete on #1? No. Just no. Companies like OpenAI (ChatGPT), Google (Gemini), and Anthropic (Claude) simply have a better solution for #1, full stop, end of story. A web site – even a free one – can’t beat ChatGPT’s ability to integrate directly with your development environment, review your code & database, and recommend specific answers for the problem you’re facing. Game over.

Can Prosus compete on #2? No. The existing answers (as of April 2, 2024) are available for free with nearly no restrictions. The horse is already out of the barn. Moving on.

Can Prosus compete on #3? If ChatGPT and their friends win on #1 and #2, then the default place for developers to find answers is no longer the web browser. (It’s ChatGPT or Copilot or whatever). Whatever happens next is going to be intriguing. Today, you and I are conditioned to think, “I’ll post that question on Stack or a forum.” Tomorrow’s developers will not have that same bias:

  • Maybe the dev will prompt ChatGPT, “Can you find me answers online for this?” In that case, the LLM will search the web and summarize – and Prosus won’t stand a chance of convincing the user to post the question at StackOverflow.com.
  • Maybe the dev will open their web browser and ask the question. In that case, the search engine company will try to summarize answers too. These days, both Google and Bing try to avoid landing you on actual web sites, and try to give you the answers on their own pages instead, whether it’s AI-summarized answers or hallucinations or web page summaries next to each site.
  • Maybe the dev will go to the Github repo for the related project, and post a question there.

I don’t see an easy way for Stack Overflow to inject themselves into that workflow in the year 2030. I’m sad about that because I have a long personal history with Stack Overflow. At the same time, I’m also kinda glad that the original founders, employees, and advisors (me included) were able to cash out thanks to Prosus’s $1.8B overspending just before the generative AI boom hit.

Prosus needs solutions fast: Stack is now losing $150,000 per day. Prosus’s 2024 annual reports noted that Stack Overflow had $98M in incoming revenue – but lost $57M. I can understand why managers might flail at a company’s switches and dials trying to find a way to stop the financial bleeding.

One of the dials they’ve been flailing at is turning down community access to the past answer data, aka business part #2. In their minds, they’re trying to stop OpenAI/Google/Anthropic from making so much money on the back of Stack’s answers. Earlier this year, Prosus tried to pump the brakes on providing the data dumps in XML format on a regular basis, and there was some community outrage, so they relented. However, they’re back: last week, Prosus announced they’re limiting access again.

Based on what Prosus is saying in that post, going forward, I don’t think Prosus will approve of me redistributing new data dumps in a database format. I’m not going to waste time or energy fighting that battle – I’d rather they spent their own energy trying to figure out a way to keep StackOverflow.com a viable business concern going forward. Hopefully they find fun, productive ways to do that, ways that bring the community together onto Prosus’s side rather than turning consumers against Prosus.

However, if Prosus management is willing to limit the data dump, then I have a bad feeling that more barriers are coming over the years. Next, they’ll make answers harder to access for people who have an ad blocker, or who aren’t signed in, or who haven’t paid for a “premium” Stack membership. I’m not mad at them about this, because I don’t have any answers to turn the business around either, and I haven’t heard from anybody who does.

You either die a hero or live long enough to see yourself become the arch-enemy.


[1] Technically the company Stack Overflow has a couple other parts: advertising and Stack Overflow for Teams. Both of those business models are at risk due to AI as well. Their other attempts at diversification, like Articles and Jobs and Developer Story, never caught on.

View Details

I went through your top-voted questions from https://pollgab.com/room/brento while in front of the National Gallery for Foreign Art in Sofia.

Here’s what we covered:

  • 00:00 Start
  • 03:12 MyTeaGotCold: If all of my columns are nvarchar, is there a performance benefit to always wrapping strings in N”? My tests have been inconclusive.
  • 03:50 SadButTrue: Hey Brent, most of our Azure SQL DBs have top wait stats related to parallelism (CX***) and performance is not great. As we cannot modify the cost threshold for parallelism in Azure SQL, what other techniques can we use to reduce the waits associated with parallelism?
  • 05:00 Dom: Hi Brent, I noticed something strange on a SQL Express 2012. I’m looking at the “Visible online” CPU and was expecting to see 4 (as Express limits to 4 cpu or 1 socket) but it shows 8 visible online cpu… Am I missing something or is my SQL Express really using 8 CPU ? Thanks !
  • 05:36 dba jr: hi Brent, in my company users can design any query they want. for example they can choose multi column for order by or in where clause . i mean queries in APP are not fix. but they tell me queries are slow. tables have million rows. how can I handle this.
  • 07:10 DBA in VA: SQL 2019: What causes a query not to use the execution plan I’ve forced in the query store? Isn’t that the whole idea of the forced plan??
  • 08:00 Ruby Sunday: Is creating a NC index that mirrors the clustered index to avoid blocking considered a bad practice?
  • 09:30 TheyBlameMe: Hi Brent. What’s you opinion of this MS recommendation to “prevent lock escalation” for long running batch operations? BEGIN TRAN; SELECT * FROM mytable (UPDLOCK, HOLDLOCK) WHERE 1 = 0; WAITFOR DELAY ‘1:00:00’; COMMIT TRAN;
  • 10:40 DanishDBA: Hi Brent, my friend needs to create an index on a highly used table on a SQL Server 2019 SE (FCI). On a copy of the db on the same server he knows that it can take up to 4 minutes. The goal is to minimize the impact, as a service window is not allowed. What is the best approach?
  • 11:48 JustWondering: Been suspicious that something “outside” of SS is the problem but don’t know how to prove it. Changed from using JTDS JDBC driver to MS JDBC driver and saw 40+% improvement in runtimes. How could I find what the MS driver is doing different vs JTDS? QryPlans seem the same. Thx.

View Details

You already use sp_Blitz and the rest of the free, open source First Responder Kit to give your SQL Servers a health check now and then.

But let’s be honest: you don’t do it often enough.

You wish you had an easier way to know when your backups stop working, when corruption strikes, when a poison wait is detected, or when a new SQL Server patch comes out for one of your servers.

Good news! We’ve now got a free version of SQL ConstantCare®!SQL ConstantCare® is our simple monitoring product that you install on a jump box or VM. It connects to your SQL Servers, Azure SQL DB, Amazon RDS, etc. just once per day, gathers diagnostic data, and sends it to our processing servers in AWS. We generate a single daily email per server telling you specific, actionable tasks that will make your databases safer.

The full-blown $695/year version of SQL ConstantCare® gives you performance advice on stuff like query plans, indexes, memory settings, and wait stats, but there are a lot of folks out there who just don’t need that. They can’t fix the databases, queries, or indexes, and they just wanna know that the server is healthy.

That’s where our free health-only monitoring comes in. Sign up here for free, then download the installer, and follow the installation instructions. In a matter of minutes, you’ll get an email, and then again once a day – but only when we’ve got stuff you actually need to do on the server. Otherwise, we leave you alone to do the other important stuff you gotta do every day.

Why are we doing this? What’s the catch?For now, it’s for the first 100 free-tier users. I want to be careful as we scale this in a way that I can afford it, and Richie & I can support it. We’re pretty confident we can do it at a much larger scale, but we’re starting small.

It’s easy for us to support because we’re not doing anything complex like putting agents on SQL Servers, or running 24/7 monitoring. The app just runs on your jump box as a scheduled task, once per day, and that’s it.

It’s cheap for us to provide because the health-only processing costs us less than $1 per monitored SQL Server per month. We designed SQL ConstantCare® to be serverless and cloud-native right from the start, and Richie’s done a lot of work keeping the code and database lean and mean, so scaling has been pretty easy.

Our back end is fully cloud-hosted, which means your diagnostic data goes up to our services in AWS. If you’ve got questions about how that works, check out how we collect, transmit, and store your data and the frequently asked questions. To help us with GDPR compliance, we automatically delete all data older than 30 days. We won’t ever offer a version of SQL ConstantCare® that you can host yourself – we rely on too many AWS services, and helping you set all that up and troubleshoot it would make the price tag crazy high. If you want your own private monitoring, you’re better off buying a conventional 24/7 monitoring app. Of course, those are more expensive, and priced per monitored server – but if you want that level of control, that’s the price you pay. (Literally.) We’re trying to help as many people as we can here, as inexpensively as possible.

The signup process is a little wonky, not as smooth as I’d like. When you click the signup link, you’ll be asked to sign up with an email or Google. If you’ve bought training classes or software from me in the last few years from training.brentozar.com, you can use the same login. If you hit any roadblocks signing up and you can’t figure out how to get past ’em, email Help@BrentOzar.com and include a screenshot of the full browser, including the URL you’re on.

I hope this helps make your job easier. Like the First Responder Kit, this here blog, and the tons of videos we put out across my YouTube channel, TikTok, LinkedIn, etc, I really want to help do as much as I can, for free. That way, when you need training or consulting, you’ll remember who loves ya, baby. Enjoy!

View Details

For T-SQL Tuesday this month, Louis Davidson suggested we give our past self some advice.

I’d tell myself, “Use ‘we’, not ‘you’.”

For years, when I gave advice, I’d say things like:

  • “You’re doing A, when you should really be doing B instead.”
  • “Your code has a problem right here.”
  • “Your network settings are wrong, and you should change them to this instead.”

The very word ‘you’ sets up a confrontational tone that puts the recipient on the defensive. They can’t help but react by taking things personally. We’re just humans, meatbags of emotion.

Instead, use words like ‘we’ and ‘our’ that group us together. We’re on the same team, and our common enemy is technology. Dagnabbit, technology sucks hard. It’s always out to get us, to make our lives miserable, to refuse to work the way it says it’ll work in the manual.

Once we (see what I did there) get started using the term ‘you’ early on in our careers, it’s a really hard habit to break. I know that, because I’ve been trying to break it for years.

I do use the term ‘you’ a lot in blog posts and videos that are purposely designed to be confrontational and drive engagement. That’s on purpose. However, when I wanna give advice to someone on my own team, I try to remember that we are indeed on the same team, and I need to communicate that by using the word ‘we.’

View Details

I was honored to speak at the Present to Succeed conference in Sofia, Bulgaria, run by a former SQL Server MCM. Sofia is a beautiful city, and the gorgeous Patriarchal Cathedral of St. Alexander Nevsky (Wikipedia) was close to my hotel, so I dragged my tripod over there for an Office Hours session.

Here’s what we covered:

  • 00:00 Start
  • 01:19 Live is Life: After a migration to a new db, the old 3TB db is now read only. My friend is enabling row compression on the biggest tables/indexes and already got down to 1,5TB. The goal is to get faster reads and a smaller db. What are your thoughts about this? Is there a better way?
  • 02:40 MyTeaGotCold: Is Enterprise Edition generally seen as the norm? Blogs and particularly the official docs rarely point out that something isn’t available in Standard, but I’ve gone my entire career without seeing it.
  • 03:20 EthicalDBA: Hey Brent, have you ever faced any moral/ethical issues in your DBA career that caused you to really question the task you were working on?
  • 04:35 With NeinLock: Greetings! As someone who is a household name when it comes to the SQL Server community, have you noticed members of the younger generation joining the community to give back and share knowledge? If yes, are there any you recommend following?
  • 08:22 Roger ap Gwilliam: What’s the scariest RDBMS you have worked with?
  • 08:58 DT_DBA: Do you think using the FORCESEEK hint “everywhere” is okay? (same as how some people use NOLOCK). I have a client that has started doing this. They aren’t specifying which index to use, just doing things like “select * from table WITH (FORCESEEK) join view WITH (FORCESEEK) …”
  • 09:40 handysql: Helmet on the shelf. Is that for show or do you have a harley/rocket in the garage?
  • 11:35 Mike: Is there a good criteria that can be used to tell if a query is OLTP or OLAP query ? Is it number of seconds (duration, or cpu time), or number of logical reads, or something else ?
  • 12:48 VegasDBA: Hi Brent! Ever do any big physical to virtual conversions? I’ve been tasked with a very aggressive timeline to convert several physical SQL AGs to VMs. I was considering using AGs or distributed AGs to fail them over. Was curious of your thoughts and opinions.
  • 13:46 Mike: Is there a good up-to-date article that describes differences between Junior, Middle and Senior DBA in SQL Server (and maybe Azure SQL ?). And where can you develop next after becoming “Senior” ?
  • 15:53 Davros: When a traditional clustered index table starts to having too many indexes is this an indication that the table should be using column store?

View Details

Next Tuesday, pricing on the 3-day tickets for the PASS Data Community Summit goes up to $2,095.

But if you register right now, plus use coupon code BRENTO24, it’s just $1,745.

It’s one in-person conference that covers Microsoft SQL Server, Azure, PostgreSQL, Snowflake, Oracle, and more. So many of us (me included!) are working with multiple databases these days, and it’s hard to find a single event with this kind of coverage.

I’m also teaching a 1-day pre-conference workshop on Monday, Tuning T-SQL for SQL Server 2019 and 2022. That’s an additional $595, and you can also sign up for another pre-conference workshop on Tuesday. There are great options in there including Query Quest with Erik & Kendra, Microsoft Fabric in a Day, PostgreSQL Fundamentals, Power BI Architecture, and a SQL AI Workshop run by Microsoft folks.

Go register now, and I’ll see you in Seattle!

View Details

At the PGConf.dev, where Postgres developers get together and strategize the work they wanna do for the next version, I attended a session where Matthias van de Meent talked about changing the way Postgres stores columns. As of right now (Postgres 17), columns are aligned in 8-bit intervals, so if you create a table with alternating columns:

  1. MyBitColumn1 – 1 bit used
  2. (7 bits wasted for alignment to get to the next byte)
  3. SomeOtherColumn – any other datatype, but not a bit
  4. MyBitColumn2 – 1 bit used
  5. (another 7 bits wasted for alignment)

Matthias pointed out that was inefficient, and that Postgres should separate physical column order from logical column order. Under the hood, it should just store:

  1. MyBitColumn1 – 1 bit used
  2. MyBitColumn2 – 1 bit used
  3. (6 bits wasted for alignment)
  4. SomeOtherColumn – any other datatype

Microsoft SQL Server already does this with bits, as the documentation explains:

The SQL Server Database Engine optimizes storage of bit columns. If there are 8 or fewer bit columns in a table, the columns are stored as 1 byte. If there are from 9 up to 16 bit columns, the columns are stored as 2 bytes, and so on.

To demonstrate that, I whipped up a demo script showing two table creations: one with the bit columns scattered around through the table, and one where they’re all grouped together:

CREATE DATABASE TestColumnAlignment;GOUSE TestColumnAlignment;GOCREATE TABLE dbo.Disorganized(Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,TinyInt1 TINYINT,Bit1 BIT,TinyInt2 TINYINT,Bit2 BIT,TinyInt3 TINYINT,Bit3 BIT,TinyInt4 TINYINT,Bit4 BIT,TinyInt5 TINYINT,Bit5 BIT);CREATE TABLE dbo.Organized(Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,Bit1 BIT,Bit2 BIT,Bit3 BIT,Bit4 BIT,Bit5 BIT,TinyInt1 TINYINT,TinyInt2 TINYINT,TinyInt3 TINYINT,TinyInt4 TINYINT,TinyInt5 TINYINT);INSERT INTO dbo.Disorganized(Bit1, Bit2, Bit3, Bit4, Bit5, TinyInt1, TinyInt2, TinyInt3, TinyInt4, TinyInt5)SELECT 1, 1, 1, 1, 1, 1, 1, 1, 1, 1FROM GENERATE\_SERIES(1, 10000000);INSERT INTO dbo.Organized(Bit1, Bit2, Bit3, Bit4, Bit5, TinyInt1, TinyInt2, TinyInt3, TinyInt4, TinyInt5)SELECT 1, 1, 1, 1, 1, 1, 1, 1, 1, 1FROM GENERATE\_SERIES(1, 10000000);GOEXEC sp\_BlitzIndex @Mode = 2; sp_BlitzIndex shows that both tables have the same size:

If we add another bit column to both tables:

ALTER TABLE dbo.DisorganizedADD Bit6 BIT;ALTER TABLE dbo.OrganizedADD Bit6 BIT;GOEXEC sp\_BlitzIndex @Mode = 2;GO Size still remains the same:

Because SQL Server’s just making a metadata-only change, noting that 1 of the 8 bits in the bit-designated space is now available for use by the new Bit6 column. To really drive that point home, let’s go back and update the new Bit6 column to be 1:

UPDATE dbo.Disorganized SET Bit6 = 1;UPDATE dbo.Organized SET Bit6 = 1;GOEXEC sp\_BlitzIndex @Mode = 2;GO And then check the space used again:

Yep, still 194MB. Good work, Microsoft.

The more I learn about Postgres, the more I appreciate so many little things that Microsoft has done over the years for performance & space optimization. The one that’ll really surprise you is that Postgres still doesn’t have table or index compression yet, although it does offer value-level compression.

View Details

I’m not talking just about Microsoft SQL Server specifically here, nor T-SQL. Let’s zoom out a little and think bigger picture for a second: is the SQL language itself a problem?

Sometimes when I talk to client developers, they gripe about the antiquated language.

The order of a SELECT statement doesn’t make any sense. You shouldn’t state what you’re looking for, before you even say where you wanna get the data from. The FROM should really go first so that query-completion tools like IntelliSense have a fighting chance to help you write the SELECT part. If we started writing our queries like this:

FROM dbo.Users uINNER JOIN dbo.Posts p ON u.Id = p.OwnerUserIdSELECT ... Then as you started typing stuff in the SELECT, you could actually get useful stuff out of IntelliSense. How many times have you started typing a query, and query completion tools start throwing all kinds of system functions at you? Idiotic.

Exception handling is a painful mess. Let’s be honest here: the majority of stored procedures and functions out there don’t have error handling. They YOLO their way through the data, hoping and praying that things are as we expect, we have the right permissions, structures haven’t changed, and the data is in a useful state. Everybody looks the other way and mumbles, “We’ll handle errors on the application side,” when in reality those errors are either thrown directly at the innocent user, or simply suppressed and not logged anywhere.

It’s not really a standard. Oh sure, SELECT/FROM/WHERE/ORDER BY works in most databases, but even trivially simple applications break if you try to port them from one database management system to another. Your skills transfer in a similar way: even if you’re great at T-SQL exception handling, you’re still gonna have to tweak the way you do it in Postgres. The concepts are standard, but the specifics are different.

Unit testing is a pipe dream. App code developers know if their code changes will break something. Database developers just punt their stuff into development, run the query a few times, nod because no errors get thrown, and then toss it into production. When code breaks weeks or months later, all we hear is, “Nothing’s been changed.”

So why haven’t we moved on past SQL?In some ways, we have, with object-relational mapping (ORM) tools like Entity Framework, Hibernate, and Django. The database administrator readers here in the audience usually cringe when they hear those words, but the reality is that developers leverage those tools heavily to build new applications. I don’t blame them. I would too, for all the reasons I talked about above.

What those tools do is translate your desires into SQL, though, which brings us right back where we started. Often, the SQL they generate sucks for performance, thus the typical DBA’s feelings about ORMs. So why haven’t we got a new standard way for applications to talk directly to databases, in a secure, performant, and easy-to-write way?

It’s not for lack of trying: at least once every 6 months, I see a post on HackerNews about a better replacement for SQL. Someone puts a lot of thought into the problems, puts a lot of work into a replacement, and then proudly announces it.

And nobody uses it.

Because SQL is the lowest common denominator that works damn near everywhere, for values of “works.”

It works on the back end. Remember when NoSQL came out, and everybody was all “databases r doomd”? And remember what business users said when they wanted to run their reports? NoSQL persistence layers pretty quickly changed their tune, saying, “Oh, well, uh, we meant Not Only SQL, that’s what we meant,” as they struggled to quickly slap in SQL compatibility. Even MongoDB, king of NoSQL, implemented SQL support.

It works on the front end, especially the reporting front end, which is what managers care about. The people who sign the checks wanna see their data in Power BI and Excel. Every new reporting tool that comes out, in order to check boxes and say they’re compatible with every database, implements SQL support. Oh sure, these tools write horrific queries, but they check the box to say they can get data out of all your different persistence layers, and they do it with SQL first because it’s cheap and easy to support lots of databases that way.

I’ll leave you with an amusing quote from Bjarne Stroustrup:

There are only two kinds of languages: the ones people complain about and the ones nobody uses.

View Details

I went through your top-voted questions from https://pollgab.com/room/brento before heading out to PGConf.dev in Vancouver.

Here’s what we covered:

  • 00:00 Start
  • 01:43 Poul J: Hi Brent. Can you give some examples of how a CHECK() constraint is used by the optimizer. Is it similar to a filtered index… Or is there more to it?
  • 03:54 RadekG: Hi Brent, Could you explain when high wait statistics of parallelism type indicate a problem? I wander what is even a point in monitoring them… (but I am almost sure that I am missing something obvious here)
  • 04:51 Ricardo: My secret-sauce as a DBA was getting sophisticated work done through the GUI (EG: Always On). Now with Azure Portal, Databricks, etc, the GUI seems to change daily. Do you think the days of the GUI are numbered? (the days of knowing a GUI intimately, like an engine bay).
  • 05:45 tibbler: Hi, imagin you have complex structured data in a database. You’d like to archive them for long term, the structure should be preserved too. Would you recommand a database for this purpose?
  • 06:57 Ricardo: When performance tuning what ball-park figures do you use relating [time] to [rows returned]. EG: What is a reasonable amount of time to return 200,000 rows in a report?
  • 08:48 Ozan: Hi Brent, when using SQLQueryStress with enough number of threads and iterations to get THREADPOOL waits, i can still see enough available worker threads after summing up the active_workers_count field in dm_os_schedulers. How is that possible? Thanks
  • 09:50 Andrew: How transferrable is Oracle DBA experience to the Microsoft stack? I’m reviewing job applications for someone on my team, we use the Microsoft stack, but have a few applicants with years of Oracle experience – do you see the concepts as equivalent or transferrable?

View Details

For this week’s Query Exercise, I asked you to write a better query than ChatGPT wrote. Your goal was to find the best days and times to post questions on Stack Overflow.

I found it interesting that a lot of the initial answers focused on the times when there were the most questions, or which questions were the most highly upvoted. For me, the best time to post a question is when you have the highest likelihood of getting the right answer, quickly.

When someone posts a question, they can accept an answer as the right one. You can see it by looking for checkmarks next to an answer. The checkmark indicates that the answer was accepted by the original question-asker.

The accepted answer may not be the best one overall, especially as additional answers come in later over time. However, the accepted answer was good enough for the person who asked the question – and when I’m asking a question, that’s what my goal is, to get an answer that’s good enough to solve my problem, and move on.

In the Posts table where questions & answers are stored, there’s an AcceptedAnswerId column. If a question has an Id in the AcceptedAnswerId, then that’s the Posts.Id for the answer row.

Let’s try this:

SELECT TOP 100 DATENAME(weekday, pQ.CreationDate) AS DayOfWeek,DATEPART(hh, pQ.CreationDate) AS HourOfDay,AVG(DATEDIFF(mi, pQ.CreationDate, pA.CreationDate)) AS AvgMinutesToAnswer,SUM(1) AS QuestionsAnsweredFROM dbo.Posts pQINNER JOIN dbo.Posts pA ON pq.AcceptedAnswerId = pA.IdWHERE pQ.PostTypeId = 1 /* Question, but not really needed */GROUP BY DATENAME(weekday, pQ.CreationDate),DATEPART(hh,pQ.CreationDate)ORDER BY AVG(DATEDIFF(mi, pQ.CreationDate, pA.CreationDate)),SUM(1) DESC; The results in the 2018-06 version of the Stack Overflow database:

It’s looking like weekend mornings are the best times to post questions – but even then, it takes a week to get to a good answer! You might think (or at least I did), “Well, if it takes a whole week, does it even make a difference when I post the question?” Let’s flip the sort order and look for the worst times:

That’s kinda wild – it’s weekday afternoons! (We’ll set time zones aside for this, but that’s a whole ‘nother exercise.) That made me wonder: if we only group the data by day of week, what does it look like?

SELECT DATENAME(weekday, pQ.CreationDate) AS DayOfWeek,AVG(DATEDIFF(hour, pQ.CreationDate, pA.CreationDate)) AS AvgHoursToAnswer,SUM(1) AS QuestionsAsked,COUNT(DISTINCT pA.Id) AS QuestionsAnsweredFROM dbo.Posts pQLEFT OUTER JOIN dbo.Posts pA ON pq.AcceptedAnswerId = pA.IdWHERE pQ.PostTypeId = 1 /* Question, but not really needed */GROUP BY DATENAME(weekday, pQ.CreationDate)ORDER BY AVG(DATEDIFF(hour, pQ.CreationDate, pA.CreationDate)) I added a couple more columns because the results are pretty conclusive:

Post your questions on the weekends. Sure, there are way less questions coming in at that time – but that’s also when you get more eyeballs on your questions because you have less competition. You’re more likely to get a good answer, faster, when you’re not competing with other questions.

Is the moral of the story that ChatGPT’s answer was bad? No, or at least, no worse than some of the answers us meatbags came up with initially. I think the key to asking a good data question is to keep following up with more questions. What do the query results show? Where do we think the loopholes are? What’s the real business objective that we’re trying to achieve? How do we gauge the accuracy of an answer?

View Details

I’m coming to San Diego on Sept 13-14 for SQL Saturday San Diego!

I’m teaching a one-day pre-conference workshop on Friday, September 13th.

Tuning Databases In One Day – You’ve got production databases in SQL Server or Azure SQL DB, and you want to make ’em faster. You need to identify the database’s bottleneck, prove the root cause, and then recommend fixes. You want to make the right choice for each bottleneck – should you do index changes, query tuning, or server-level settings?

The class will be a mix of 50% slides, and 50% live demos, with plenty of time for Q&A. We’ll even cover 3 sample client findings for the most common performance issues so you can see how I explain the issues to my own clients, and give them proof.

I’m Brent Ozar, and I do this for a living. In one day, I’ll teach you the exact same techniques I use with my clients. I can’t teach you everything about what I do in one day – but I’ll teach you the most important stuff.

Register for the $149 pre-con here, then register for the free SQL Saturday here. Only 100 pre-con tickets are available, so move quickly!

View Details

While in a hotel room in Vancouver for PGconf.dev, I strapped on my Apple Vision Pro headset to take your top-voted questions from https://pollgab.com/room/brento. Somehow, the latest Vision OS update gave me a 1980s 3rd Bass haircut.

Here’s what we covered:

  • 00:00 Start
  • 01:03 MyTeaGotCold: Have you ever seen SSISDB migrated on to a new server without difficulty? I’ve never seen it go smoothly.
  • 01:52 ThatSteveCena: https://www.sqlskills.com/blogs/jonat… Is the juice worth the squeeze to try individually tuning your index fill factors, or are there better means of performance gains?
  • 02:40 Joseph: Getting a corrupt database message when running maintainance but the DB ID does not exist “DESCRIPTION: Corruption in database ID -4294967288, object ID 60 possibly due to schema or catalog inconsistency. Run DBCC CHECKCATALOG.” Have run DBCC Checks on all user and sys dbs.
  • 04:05 TractorDBA: My friend’s security dept. decided that using the fallback cert is no longer good enough for internal network encryption. Security is not your thing, but is there a good resource who explains the ins and outs of certificate mgmt. for a large enterprise of SQL Servers?
  • 04:50 SQL_Stormlight: GrumpyOldMan had a similar issue. SQL is recommending an index but it already exists and is being used. In my case, there are only two columns. I’ve tried swapping the column order and even tried different ASC/DESC yet SQL still wants this. Maybe it’s a bug or a bad rec?
  • 05:45 aPartyPerson: My friend wonders if a View (with no WHERE and can’t be indexed due to bad life choices) used in a query could be replaced with a SP, and perform better. SELECT * FROM myV v WHERE v.typ = 1 SELECT * FROM OPENQUERY([LOCALSERVER], ‘SET FMTONLY OFF EXEC EXEC mySP @typ = 1’);
  • 06:36 KyleDevDBA: Is dynamic SQL an acceptable way to add conditional joins/filters onto a query?
  • 07:05 Ozan: Hi Brent, since MaxDOP can be set on DB level, is there still any reason why not to mix SharePoint with Non-SharePoint-DBs on the same SQL instance? Thanks
  • 08:26 SQL_theocean: Was wondering which permission is required apart from db_owner in case the user wants to make his own database online after they make them offline in SQL server 2022.
  • 09:36 MadridMoneky: We have AlwaysOn Availability Groups spanned across two data centers (~100 SQL Servers), one Data Center is migrating, unavailable for two weeks. How do we Manage the AGs? Do we have remove the DBs from the AG and reseed thousands of DBs when secondary is back online?
  • 10:32 Richard at Analytic: Visual Studio Code vs Visual Studio. It appears that Microsoft is favoring Visual Studio Code over Visual Studio whenever there is no GUI or only an HTML UI associated with the project. What is your opinion on this?

View Details

What are the best days of the week and times of the day to post a question at StackOverflow.com?

It seems like a simple question, but it’s surprisingly nuanced. I asked ChatGPT’s latest version, 4o, and its answer made me laugh out loud. First off, the T-SQL is terrible: it creates a completely unnecessary temp table. However, a bit of congratulations are in order: at least ChatGPT is trained on the Stack Overflow database schema, and it understood that you have to filter for PostTypeId = 1 for questions (and even put a comment indicating that!)

ChatGPT’s answer assumes that our criteria for a good question is the question’s Score – and I think that’s not a bad assumption to make. After all, a lot of people use Stack Overflow as a game, trying to maximize their reputations. However, let’s assume that we post questions in order to get answers.

I followed up by asking ChatGPT:

What are the best days of the week and times of the day to get good answers quickly?

Again, ChatGPT gets a low score for its generated T-SQL, a high score for understanding the database without additional training, and a flat out failure for botching the query and the results:

So, with that in mind, can you do better than ChatGPT?

Any size version of the Stack Overflow database will work for this exercise. (ChatGPT’s query even fails on the tiny 10GB version.)

For this exercise, I’m not expecting a specific “right” or “wrong” answer – instead, for this one, you’re probably going to have a good time sharing your answer in the comments, and comparing your answer to that of others. Feel free to put your queries in a Github Gist, and include that link in your comments. I’ll check back next week with my thoughts. Have fun!

View Details

“The last person must have set it up that way.”

“The last person wrote that code.”

“The last person just didn’t configure it right.”

You can use that excuse for 6 months.For six months, you’re allowed to get up to speed on the company’s politics, the intricacies of the app, and the responsibilities of different departments. You’re allowed to prove yourself to your peers, building up social capital so that they’ll take your recommendations and run with ’em..

You can take your time figuring out whether the last person knew what they were doing or not. You should start by assuming that you did, and give them some benefit of the doubt because they were under time pressure just as you are now. If you’re generous and curious, you can even try to contact them through unofficial channels, offer to buy them lunch, and chat about their experiences at the company.

But after 6 months, the statute of limitations is up.TIME’S UPAfter that, you’re not allowed to blame “the last person” anymore.

The last person can no longer be prosecuted for their crimes against the database, and they are absolved of any guilt. It doesn’t matter who was originally responsible last year: the person responsible is now you.

So pull yourself up by the bootstraps, write up a health check with sp_Blitz, and start working through the problems. Put the correct backups and corruption checking in place. Schedule that outage. Apply the patches. Fix those linked servers using the SA login.

Because after 6 months, if you’re not fixing these problems, the clock is already starting to tick down to when you will be referred to as “the last person”, and they’re going to roll their eyes when they talk about your inability to get the job done.

Just like you’ve been doing about “the last person” for over 6 months.

View Details

While in Nashville for a creators conference, I went through your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:38 Bisal Basyal: What is the best way to manage roles in sql server in Azure VMs (multiple). We want separate logins for each users but it should be same on all Azure SQL VMs. We are currently using windows Cred. setting credentials on credential manager for that server IP but it is too slow.
  • 01:06 MyTeaGotCold: I’ve only ever heard bad things said of MySQL, but it’s often above SQL Server in surveys. What am I missing?
  • 02:27 FIN7: What are the top gotcha’s you have run into when migrating SQL onprem to Azure SQL Managed instance?
  • 03:39 Unspoiled: is there any database level statistic you would recommend to monitor to know the impact or pressure a single database is generating. the goal being to understand how much pressure a single database is generating with multiple on a the server.
  • 04:59 Poul J: Hi Brent. I was wondering if you are using a dedicated tools for investigating complex query plans?
  • 05:08 SteveE: Hi Brent, I’m looking at your SQL ConstantCare® Population Report: Spring 2024 and can see a spike for Azure SQL DB in 2022 Q3 which then drops back to approximately the prior level in the next quarter. Are you able to offer an insight as to why this is please?
  • 05:41 Kansas4444: Do you often see CLR function / procedure used and what impact it has on performances ?
  • 06:08 Mattia Nocerino: Hi Brent! I’ve inherited a 3 node cluster (2 nodes FCI + 1 node AG) but it keeps going down for all the wrong reasons. I’ve never built nor managed a similar infrastracture. Could you point to some resources to get me started figuring out what’s going on! Hope you’re doing good!
  • 07:50 BackupsAreImportant: What’s the drawback to implementing a backup strategy that only used the read-only node of an AG? You can take COPY_ONLY backups and log backups from there. I know the COPY_ONLY won’t affect the log chain but you can still do restores and apply logs. Seems wrong but why?
  • 09:02 ThatSteveCena: With file system advancements on Windows, should we consider formatting MDF/LDF drives using ReFS or stick with NTFS?
  • 09:56 Peter: Hi Brent, some devs have started slapping OPTION (NO_PERFORMANCE_SPOOL) on their queries. This is not something you covered in your courses. Is it a real solution to a genuine problem or a workaround to a problem they could or should be fixing a better way.
  • 11:23 DATA cow: ALTER DATABASE DBname SET MEMORY_OPTIMIZED = ON; Version : 2019 what benefit we get by enabling ?I understand frequent data will loaded to memory. is that mean are we end up with run out of memory or memory or server pressure ?

View Details

Ola Hallengren’s free maintenance solution is widely used as a replacement for SQL Server maintenance plans. It’s a more powerful, flexible tool for backups, corruption checking, and index & statistics updates.

If you’re using it for backups, there are two quick, easy changes that can dramatically reduce your nightly job runtimes.

First, set @NumberOfFiles = 4.SQL Server has internal bottlenecks for single-file backups, and striping your backups across multiple files removes that bottleneck. I’ve written about testing the number of files before, and in a perfect world you’d have the time to do that testing, but for starters, just try writing your backups across 4 files.

You don’t need separate drive targets or network targets – even writing the 4 files to the same volume usually produces pretty dramatic performance improvements for free.

I only do this on my user databases because the system databases are generally so small that it doesn’t matter. To set it up, just right-click on the Agent job for user database full backups, go into the step properties, and add a line for @NumberOfFiles = 4, like this:

This does mean you need all 4 files at restore time, and it means your restore scripts will be a little bit more complicated. But who cares? You’re not writing those scripts by hand in the year 2024, are you? You’re using sp_DatabaseRestore from the First Responder Kit, like a boss, just pointing it at a folder and letting it grab the most recent full, diff, and log scripts:

EXEC [dbo].[sp\_DatabaseRestore] @Database = 'StackOverflow', @BackupPathFull = 'Z:\MSSQL\BACKUP\SQL2022\StackOverflow\FULL\', @BackupPathLog = 'Z:\MSSQL\BACKUP\SQL2022\StackOverflow\LOG\', @TestRestore = 1, @RunCheckDB = 1, @RunRecovery = 1, @Execute = 'Y' Good job. Moving on – eagle-eyed folks will notice another config change in that screenshot. This next one’s going to be a little more controversial, but hear me out.

Next, set @Verify = ‘N’.By default, Ola’s backup jobs have @Verify = ‘Y’, which means after the backup command finishes, SQL Server reads the whole backup file to check to make sure it’s okay. This can massively extend your backup job times.

I’m not saying you shouldn’t verify your backups! I’m saying don’t verify them from the production box. Instead:

  • Write your backups to a network share, like a UNC path
  • Use sp_DatabaseRestore to verify them from a separate server, like DR
  • Bonus points for using sp_DatabaseRestore’s @RunCheckDB = 1 parameter, which is way better than @Verify = ‘Y’

This has a few important performance & reliability benefits:

  • Your production server’s nightly jobs finish faster
  • You really test the hell out of the backup, making sure it’s free of corruption
  • You offload that resource-intensive check work to a secondary server, not production
  • Hell, you don’t even have to pay licensing for that, because as long as you’ve got Software Assurance, you can do CHECKDB on secondaries for free, regardless of what SQL Server version you’re using

Presto: those two free, simple changes might cut your backup times by 1/3 or more. You’re welcome!

View Details

Is your company hiring for a database position as of June 2024? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Like Sixteen Candles, but different: I go through your top-voted questions from https://pollgab.com/room/brento. Strangely, my video and audio is ever so slightly out of sync in this episode.

  • 00:00 Start
  • 01:26 GuaroSql: Hey Brent! How are you? It is necessary to enable ADR in sql 2019 in order to row versioning work better? Or it is optional? I just realized it is turned off in my sql 2019 databases. Thanks!
  • 02:42 RoJo: If I’m upgrading a major version (e.g. 2016 to 2019) and build a brand new install. Can I simply Detach the old DB and attach to the new one? or is there file structure changes that Backup / Restore handle (or any other reason). Goal to save time on big DB.
  • 03:54 Nestrus: Why are views sometimes much slower than the same query executed directly in the stored procedure and what can be done to make them equally fast? The only difference I can see is, that the query directly in the SP gets parallelized and the view is not.
  • 04:58 MyTeaGotCold: Do you know any good mailing lists for peer reviewing large writings about SQL Server?
  • 05:52 Bonnie Tyler: Did you experience a total eclipse?
  • 06:00 Jökull: What are your thoughts on remoting into the production SQL Server to run SSMS? We have several power users that like to do this. What’s the best way to deal with this?
  • 07:09 CreditToMyTL: Recently, a table with wrong data caused the business to go down for a few hours. We planned to create a trigger to check who was behind these. My TL prefers creating dynamic triggers so that new tables automatically have audit logs. Is a dynamic trigger the best option here?
  • 08:13 Garreth: How do change the culture so that production dba role is less of reactive role and more of a proactive role?
  • 09:00 Jökull: Many users have permissions on the production boxed SQL Server to create SQL agent jobs. How should you track down who to contact when one of these jobs starts to fail?
  • 10:29 Ignacio: In the DBA field, is deep or wide knowledge more valuable as a job seeker?
  • 11:19 DemandingBrentsAttention: Knowing your opinion on linked servers (go fetch the data directly), what are some uses cases that you begrudgingly tolerate, or enthusiastically support?
  • 12:17 Miles: Hi Brent, Could you please give some advice (especially when it comes to introverts) on how to network with people so that, people can genuinely help in one’s career instead of having 1000’s of LinkedIn connects?
  • 13:03 Jökull: PostgreSQL now supports MySQL wire protocol. Is it inevitable PostgreSQL will do something similar for Oracle?
  • 13:52 Gabbpoll: To fabric or not to fabric. Is it worth exploring?
  • 14:34 PAul: I always put DECLAREs at the head of my code, because in VFP they were not evaluated in-line in the code flow, say in a loop or IF statement. Does SQL server do the same thing?
  • 15:23 Nostradamus: Does parameter sniffing ever happen with smaller tables or just larger tables?

View Details

Hallelujah. With current versions of Entity Framework, when developers add a mix of parameters and specific values to their query like this:

async Task<List<Post>> GetPosts(int id) => await context.Posts .Where( e => e.Title == ".NET Blog" && e.Id == id) .ToListAsync(); See how part of the filter is hard-coded (“.NET Blog”) while the other part of the filter is dynamically generated, an ID the user is looking for? That causes Entity Framework to generate a query that is partially parameterized:

info: 2/5/2024 15:43:13.789 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command) Executed DbCommand (1ms) [Parameters=[@\_\_id\_0='1'], CommandType='Text', CommandTimeout='30'] SELECT [p].[Id], [p].[Archived], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Discriminator], [p].[PublishedOn], [p].[Title], [p].[PromoText], [p].[Metadata] FROM [Posts] AS [p] WHERE [p].[Title] = N'.NET Blog' AND [p].[Id] = @\_\_id\_0 This is the worst of both worlds for SQL Server. If the query was fully parameterized, it’d get plan reuse. If the query wasn’t parameterized at all, we could turn on Forced Parameterization and get plan reuse. However, Forced Parameterization won’t do anything for the above query because SQL Server looks at it and says, “That query’s already parameterized – see, it has a parameter for @__id_0 right there! I’ll just skip it.”

In Microsoft’s example above, ‘.NET Blog’ is a hard-coded string, but the situation is much worse when that is dynamically generated. For every variation of the parameter, SQL Server sees a “new” query coming in. End result: increased CPU to compile “new” query plans, unpredictable plans, plan cache bloat, problems with monitoring tools and Query Store, and more.

Good news! The What’s New in Entity Framework 9 rundown shows a new EF.Parameter method to force parameterization:

async Task<List<Post>> GetPostsForceParameter(int id) => await context.Posts .Where( e => e.Title == EF.Parameter(".NET Blog") && e.Id == id) .ToListAsync(); Which uses a parameter now instead of a hard-coded string:

info: 2/5/2024 15:43:13.803 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command) Executed DbCommand (1ms) [Parameters=[@\_\_p\_0='.NET Blog' (Size = 4000), @\_\_id\_1='1'], CommandType='Text', CommandTimeout='30'] SELECT [p].[Id], [p].[Archived], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Discriminator], [p].[PublishedOn], [p].[Title], [p].[PromoText], [p].[Metadata] FROM [Posts] AS [p] WHERE [p].[Title] = @\_\_p\_0 AND [p].[Id] = @\_\_id\_1 Yay! Lower CPU for plan compilation, more reused plans, less memory consumed by redundant plans, and better monitoring tools.

It is a bummer that we have to wait until an estimated November 2024 for EF9 (according to that same What’s New doc), and that developers will have to touch code in order to fix it. I can’t really complain about that, though, because I’m just happy that Microsoft is adding it. EF’s query generation keeps gradually getting better, and that’s awesome.

View Details

Every year in May, I look back at when I first registered BrentOzar.com way back in May 2001.

Things were so different back then. I struggled trying to find fun, interesting ways to learn about Microsoft SQL Server. My learning options were really dry books, droning videos sold on DVD, or – brace yourself – the documentation. There weren’t blogs or YouTube videos or open source community scripts on Github.

Today, you have a bewildering number of choices when it comes to learning SQL Server. You can – and should – exhaust all of your free options first, like Google, blog posts, webcasts, and YouTube videos. Take your career as far as you can for free first – the SQL Server community is amazing!

Then, when you’re ready to take your skills and career to the next level, I’m ready for you:

Fundamentals, Yearly$195Save $200* Fundamentals classes

Sign upFundamentals, Lifetime$395Save $300* Fundamentals classes * Buy-now-pay-later available

Sign upFundamentals + Mastering, Yearly$995Save $300* Fundamentals classes * Mastering classes

Sign upThe sale ends May 31. To get these deals, you have to check out online through our e-commerce site by clicking the buttons above. During the checkout process, you’ll be offered the choice of a credit card or buy now pay later.

Can we pay via bank transfer, check, or purchase order? Yes, but only for 10 or more seats for the same package, and payment must be received before the sale ends. Email us at Help@BrentOzar.com with the package you want to buy and the number of seats, and we can generate a quote to include with your check or wire. Make your check payable to Brent Ozar Unlimited and mail it to 9450 SW Gemini Drive, ECM #45779, Beaverton, OR 97008. Your payment must be received before we activate your training, and must be received before the sale ends. Payments received after the sale ends will not be honored. We do not accept POs as payment unless they are also accompanied with a check. For a W9 form: https://downloads.brentozar.com/w9.pdf

Can we send you a form to fill out? No, to keep costs low during these sales, we don’t do any manual paperwork. To get these awesome prices, you’ll need to check out through the site and use the automatically generated PDF invoice/receipt that gets sent to you via email about 15-30 minutes after your purchase finishes. If you absolutely need us to fill out paperwork or generate a quote, we’d be happy to do it at our regular (non-sale) prices – email us at Help@BrentOzar.com.

View Details

If you’ve hard-coded installer file names, there’s a big change in this release. There are now just 2 installer scripts: Install-All-Scripts.sql, and a new Install-Azure.sql, which only installs the scripts that are compatible with Azure SQL DB. The old Install-Core scripts are gone because we’ve deprecated sp_AllNightLog, sp_BlitzInMemoryOLTP, and sp_BlitzQueryStore. Read on for why.

Wanna watch me use it? Take the class.To get the new version:

  • Download the updated FirstResponderKit.zip
  • Azure Data Studio users with the First Responder Kit extension:
    ctrl/command+shift+p, First Responder Kit: Import.
  • PowerShell users: run Install-DbaFirstResponderKit from dbatools
  • Get The Consultant Toolkit to quickly export the First Responder Kit results into an easy-to-share spreadsheet

Consultant Toolkit ChangesThis app has been awesomely stable & useful for years, but this month we finally had to pop the hood open to make a few big changes:

  • Supports Microsoft Entra multi-factor authentication (MFA)
  • Automatically retries failed connections, allowing you to more easily gather data from Azure SQL DB Serverless databases that auto-paused
  • No longer requires create-table permissions, so it works better in environments where you can pull diagnostic data but not see database contents
  • Requires .NET Desktop Runtime 7 or higher

That last bullet point refers to the machine where you’re collecting data from, typically your jump VM or laptop. I really do hate minimum requirements, but that desktop runtime is a really fast & easy install that doesn’t require a reboot. It was necessary to get the MFA authentication working.

Just to be super-safe, I’d keep the prior version around so that if you hit a weird client issue, you can still gather data. If you run into any issues, shoot us an email at help@brentozar.com and we’ll work through it with you.

I also updated it to this month’s First Responder Kit, but no changes to querymanifest.json or the spreadsheet. If you’ve customized those, no changes are necessary this month: just copy your spreadsheet and querymanifest.json into the new release’s folder. However, in the Dec 2023 release, we we did update those files, so if you haven’t updated the Consultant Toolkit in a while and you’ve customized it, read that version’s release notes about updating.

sp_Blitz Changes* Enhancement: new checks for SQL Server service & Agent service accounts that have too much permissions. (#3481, thanks Vlad Drumea.)

sp_BlitzFirst Changes* Enhancement: add 2 option for @ExpertMode to skip sp_BlitzWho output. Could already do this with the @OutputResultSets option, but this is much easier to do during emergencies. (#3486) * Enhancement: better startup/failover time detection in Azure SQL DB. (#3504) * Enhancement: new warning about approaching max worker threads. (#3491) * Fix: under heavy load, the headline news wait stats lines would underreport the number of seconds that the sample took. (#3507) * Fix: when the Hekaton “Garbage Collection in Progress” warning fires, mention that it can also be caused by a stressed-out memory-optimized TempDB. (#3488) * Fix: don’t show the plan cache result set if it’s not asked for in @OutputResultSets. (#3492) * Fix: incorrect URL for slow data file reads. (#3483, thanks Matt Mollart.)

sp_BlitzIndex Changes* Enhancement: performance tuning by skipping queries we don’t need depending on the mode. (#3462, thanks Erik Darling.) * Enhancement: skip filtered indexes checks if they don’t have permissions to query sys.sql_expression_dependencies. (#3522) * Fix: restore SQL Server 2014 compatibility. (#3452, thanks Brianc-DBA and others for reporting.) * Fix: unreachable databases are now excluded from the total database count. (#3516, thanks Gary Hunt.) * Fix: using DB_NAME() in more places for consistency. (#3517, thanks Gary Hunt.) * Fix: fixed typos. (#3519, #3515, #3512, thanks Gary Hunt.)

sp_DatabaseRestore Changes* Enhancement: during installation, if they don’t already have Ola’s scripts, explain why they’re about to see warnings. (#3499)

Deprecating sp_BlitzInMemoryOLTP, sp_BlitzQueryStore, and sp_AllNightLogsp_BlitzQueryStore was originally written by Erik Darling when he worked here. He’s moved on to start his own excellent company, plus his own sp_QuickieStore. You should be using that instead.

sp_BlitzInMemoryOLTP was always kinda distributed as a courtesy – the real home for it is in KTaranov’s Github repository, and you can still find it there. It hasn’t been updated in over 6 years, and I’ve never seen anyone using it, so I’m removing it to streamline support issues.

sp_AllNightLog was a ton of fun when we built it several years ago, but it’s consistently had a problem. Companies start using it, then decide they want to build something even more ambitious, typically a C# service with robust error handling and scheduling. sp_AllNightLog isn’t the kind of thing I want to encourage beginners to use – it’s complex.

So when Reece Goding started working on cleaning up sp_BlitzQueryStore’s code, I decided that now was the time to deprecate stuff we no longer use or recommend. You’re definitely welcome to continue to use ’em if you get value out of ’em! I’ve going to move these procs into the Deprecated folder, plus simplify the installation scripts. For the rest of 2024, the only installer script will be Install-All-Scripts.sql.

For SupportWhen you have questions about how the tools work, talk with the community in the #FirstResponderKit Slack channel. Be patient: it’s staffed by volunteers with day jobs. If it’s your first time in the community Slack, get started here.

When you find a bug or want something changed, read the contributing.md file.

When you have a question about what the scripts found, first make sure you read the “More Details” URL for any warning you find. We put a lot of work into documentation, and we wouldn’t want someone to yell at you to go read the fine manual. After that, when you’ve still got questions about how something works in SQL Server, post a question at DBA.StackExchange.com and the community (that includes me!) will help. Include exact errors and any applicable screenshots, your SQL Server version number (including the build #), and the version of the tool you’re working with.

View Details

In some of the Query Exercises posts here, you might have noticed links over to similar query exercises at SmartPostgres.com, and the free read-only version of the Stack Overflow database I’m hosting there. I’ve held off the questions for long enough: it’s time to discuss what I’m up to.

First off, BrentOzar.com is staying Microsoft-focused. The ~100K of you who subscribe and visit regularly can breathe a sigh of relief. I’m not going to shove Postgres down your throat, hahaha. From time to time, at the bottom of SQL Server focused posts, I may add a section talking about how Postgres approaches the same problem, but only if I think it’s really interesting learning.

The blog posts, videos, classes, etc here at BrentOzar.com will be for people who work with SQL Server, Azure SQL DB, and Amazon RDS SQL Server every day. My volume of blog posts won’t be declining here – in fact, because I’m reusing the same homework challenges across both SQL Server and Postgres, I’m actually worried about the post count going up, hahaha. I’ve got stuff scheduled out for over a month already.

The new SmartPostgres.com is a separate site that is focused on developers and data professionals who work with PostgreSQL every day. It is NOT “Postgres for SQL Server people.” Don’t subscribe over there unless you use Postgres as part of your job. If you’re only just mildly curious, stay here at BrentOzar.com, because I already overwhelm your in-box and because I’ll include neat Postgres trivia over here.

When I started building SmartPostgres, I decided to host a public-facing Stack Overflow database on AWS Aurora Postgres Serverless because I wanted the simplest possible approach for people to follow along with the blog posts and training exercises. The typical SmartPostgres reader may never actually install a database server, ever.

Over here at BOU, I would absolutely love to host a free public SQL Server with the Stack Overflow database, but there are 4 major problems with that:

  • SQL Server licensing is hella expensive. (No, not Express Edition, because it only works for tiny databases and would be utterly overwhelmed each time I publish a blog post.)
  • Azure SQL DB doesn’t automatically scale up/down in milliseconds. (Microsoft’s auto-scaling is way, way behind Aurora.)
  • A lot of the BOU blog posts involve making changes to tables & indexes. I can’t do that on a shared read-only database. (For SmartPostgres, I’m focusing more on readers that may not have carte blanche on the database.)
  • The target audience of this blog is mostly used to building their own lab database servers anyway. (There are definitely readers here who’ve never installed SQL Server or deployed an Azure SQL DB, but they’re in the relative minority.)

So, why Postgres? I think it’s the best-positioned database for the next decade. It’s open source, it’s powerful, all of the cloud vendors offer a flavor of it, and perhaps most interestingly, all of the cloud vendors are trying to extend it in proprietary ways to be the best place to host your Postgres databases. This isn’t some new revelation for me – I’ve believed it for several years, and it’s why we picked Postgres for the SQL ConstantCare back end years ago. Heck, even at Microsoft Build this week, the number of Postgres mentions absolutely dwarfed the mentions of SQL Server.

I am absolutely not telling you that you need to rewrite existing SQL Server apps in Postgres. You don’t. The overall Microsoft data platform is fine (although even still, 2022 isn’t ready), and you could continue using it for years. I certainly plan to keep blogging about it here for years. It’s just that now I’m writing somewhere else, too, for another audience.

View Details

I started with audio problems, then had video problems halfway in. It’s amusing because we also discuss feeling like a SQL amateur!

Here’s what we covered:

  • 00:00 Start
  • 01:52 Does Time Really Exist: Hi Brent! What is the best way to ETL? web application, SSIS, linked server, …
  • 03:55 MyTeaGotCold: What is your vision for what SQL Server will be like in 2030? I feel like a fool for thinking it will involve In-Memory OLTP.
  • 05:49 mailbox: Hey Brent, What’s your take on switching to specializing in Open Source Database platforms( on-prem or cloud)? What would the career impact be? Seems like there are a lot of new jobs focusing on open source technologies, such as python, linux, postgreSQL,mariaDB, mongo, etc..
  • 07:03 DBANoob: Hi Brent, our company has been adopting Objective Key Results (OKR) and each team is tasked with creating new OKRs. Are you familiar with OKRs? Do you have any suggestions for a database administration team?
  • 10:38 mailbox: What’s the value of high reputation/achievement on dba.stackexchange.com or sqlservercentral.com? Have you ever seen that land someone a job or negotiate a raise?
  • 11:58 Joe Gleason: Hello Brent! Since you have been performing PolGab for many years now, do you perceive the quality of the SQL Server questions being asked going up or down? I scratch my head sometimes, but I have not been at this for a very long time.
  • 18:57 Carlini Tassio: Recently start tu learn about IA and saw about copilot being used in many microsoft tools, you think studio in the future will be launched with copilot and can help people work with data to use T-SQL?
  • 20:31 Chevy 409: What’s your favorite vintage American car?

View Details

Eitan Blumin recently wrote a post about the future of the DBA career in which he talked about the rise of jack-of-all-trades IT professionals. It’s a good post. You should read it. I did, and over the last 20 years, I’m pretty sure I’ve read a dozen variations of that post.

There’s a saying: “History doesn’t repeat itself, but it often rhymes.”

To give an example, let’s rewind the clock back to 2008. Business Intelligence was all the rage. SQL Server shipped with Analysis Services, Integration Services, and Reporting Services all inside the box. I remember hearing, “You have to learn all of these tools, or else you’re gonna be a dinosaur. Nobody’s gonna only know the engine anymore. You have to know everything else too, or you won’t get a job.”

So for a while, people were misled into believing they needed to know a little bit about everything. Unfortunately, you only have so many hours per month for learning, and a lot of people wasted a lot of time learning things – only to never actually use those tools.

It took a few years, but the ‘experts’ saying that stuff finally quieted down. The world made it clear that business intelligence and database administration are two different careers – I mean, really, they’re lots of different careers. They just happen to work with data, in the same way that gynecologists and cardiologists both work with the human body.

Today, those ‘experts’ are chanting a new song that just happens to rhyme with the old ones:

  • “You have to learn every database, or else you won’t be able to find a job working with just one!”
  • “You have to learn the cloud, or else you’ll never find a job working on-premises!”
  • “You have to learn to use AI as a tool, or else you won’t be able to get a job!”

Should you learn? Absolutely. But can you learn everything? Absolutely not. Given your limited time, you need a strategy for where your career is going. If you don’t have one, watch my 300-Level Guide to Career Internals.

You have a future. It can be as a database administrator, if that’s what you’re passionate about. It can also be as something else! But don’t let some talking head “expert” tell you what specific technologies you have to learn to stay relevant, because they can’t see the future any better than you can.

View Details

Y’all post questions and upvote the best ones at https://pollgab.com/room/brento, and I discuss ’em in my home office before tackling a client’s performance issues:

Here’s what we covered:

  • 00:00 Start
  • 00:45 Eve: When should you/should you not execute the SSMS recommended Missing Index in the execution plan?
  • 02:42 MyTeaGotCold: Logging sp_WhoIsActive and sp_BlitzFirst to a table has come up on your blog a few times. Do you still bother with it on versions that support Query Store?
  • 04:03 Frozt: Hi Brent, There is a upcoming DB we have that they configured where AG is not in automatic failover because of the dependecies of Reporting Services. Do they have other options to make AG highly available and reporting services as well?
  • 05:25 GrumpyOldDBA: Why does this variable @S get declared, even though IF evaluates as false:
  • 06:24 Luis C.: Hi Brent, Why sometimes when you use Statistics time, the CPU time is greater than the Total Exec Time?
  • 07:12 Mean Gene: Do physical reads ever matter when query tuning or just logical reads?
  • 08:57 bbk0919: Which performs better, a materialized view for a specific query? Or a non-clustered index with included columns for the same query?
  • 09:36 Luis C.: Hi Brent, Is it good or bad to put the same column in more than one index?
  • 10:04 Chris: Hey Brent, in a previous office hours you hinted at a potential Mastering Columnstore class, is this still on the horizon?
  • 10:24 Ignacio: What is your opinion of Azure SQL database watcher?
  • 11:58 Poul J: My friend asked me if it will make sence to delete autogenerated statistic on a regular basis. He is assuming that most of them are created due to adhoc queries, and he would like to save the ressources spend on updating them. I’m not sure what to respond… Any thoughts?
  • 12:40 Jökull: What is your opinion of Microsoft certifications relating to SQL Server? It seems like an opportunity to learn then forget.
  • 13:50 mailbox: Hey Brent, Do you think the avg DBA salary has decreased since 2005? I recall many DBA jobs being minimum $100,000, and now I’m seeing the average come down to like $78,000 in my area. Just curious what your thoughts are on this. Thanks!
  • 14:48 mailbox: Hey Brent, Given the news about Broadcom discontinuing free version of ESXi, what do you think the impact will be to the on-premise, SQL Server DB crowd? I’ve only ever supported SQL Server instances on vmware VMs or physical server.
  • 15:28 DadJokerDetroit: Recently, the brilliant Steve Sanderson did a great demo about Vector Search. Have you seen more demand for Semantic Search in SQL Server?
  • 15:43 Poul J: Is there a way to get information about how often the statistics of a table have been updated and how much time was spent on the updates?
  • 18:20 chandwich: Hey Brent! When do we get a tour of the office/home/garage?
  • 20:08 MustangKirby: I have hundreds of customer databases on several servers. Company policy says the dbs must be deleted if not being currently used. Other than taking all of them offline and seeing who yells, is there a way to determine the last time a db was accessed?

View Details

In last week’s post, I gave you a trigger that populated a history table with all changes to the Users.AboutMe column. It was your job to write a T-SQL query that turned these Users_Changes audit table rows:

Into the full before & after data for each change, like the earlier query from the blog post:

The trigger will always log the “before” values into the Users_Changes table, but the “after” value could be in a few different places:

  • If other changes have been made to that row, then the “after” value will be the next change for this Users.Id in the Users_Changes table
  • If no other changes have been made to that row, then the “after” value is the current state of the row in the Users table
  • If the row has since been DELETED, the “after” value isn’t anywhere!

To test your own code alongside mine, run these changes:

/* Make some changes: */UPDATE dbo.Users SET AboutMe = 'Update Numero Uno' WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = NULL WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = 'Update Part 3' WHERE Id = 26837;DELETE dbo.Users WHERE Id = 26837;GOSELECT * FROM dbo.Users\_Changes; I didn’t explicitly call the DELETE scenario out in the challenge, and to be honest, I didn’t expect anyone to think of it when they were writing their answers. The post was all about catching mangled changes to the Users.AboutMe column, and the post’s trigger focused on updates of Users rows, not deletions. However, it’s still perfectly valid for someone to delete a row – and ideally, our query should be able to handle that situation. We didn’t get an answer that returned accurate data in that scenario, and I don’t blame y’all.

It’s an edge case – and it’s even harder of an edge case to handle than it might seem once you factor in NULLs. Let’s think about possible changes:

  • The UPDATE might have set the row’s contents to NULL, in which case we want the AboutMe_After to show NULL.
  • The UPDATE might have set the row’s contents to something, but then the row was subsequently deleted (and our trigger didn’t catch that) – in which case we want the AboutMe_After to reflect that we don’t know what the UPDATE did. NULL isn’t a valid answer here because it implies that the UPDATE set the AboutMe to NULL, which isn’t necessarily true. We want to show something like a “(Unknown, Row Has Been Deleted)” warning.

So that means we can’t just slap a COALESCE in there and call it a day. We’re gonna need some tricky CASE statements.

Here’s the query I came up with, and note that I’m including the different AboutMe_v2 and AboutMe_Current data just for diagnostic purposes so you can see how NULL handling is tricky:

SELECT v1.Id AS Users\_Change\_Id, v1.AboutMe\_Before, v2.AboutMe\_Before AS AboutMe\_v2, u.AboutMe AS AboutMe\_Current, CASE WHEN v2.Id IS NOT NULL THEN v2.AboutMe\_Before WHEN u.Id IS NOT NULL THEN u.AboutMe WHEN u.Id IS NULL THEN '(Unknown, Row Has Been Deleted)' ELSE '(Unknown, My Query Messed Up)' END AS AboutMe\_AfterFROM dbo.Users\_Changes v1 LEFT OUTER JOIN dbo.Users u ON v1.UserId = u.Id LEFT OUTER JOIN dbo.Users\_Changes v2 ON v1.UserId = v2.UserId AND v1.Id < v2.Id AND v1.ChangeDate <= v2.ChangeDate LEFT OUTER JOIN dbo.Users\_Changes vBetween ON v1.UserId = vBetween.UserId AND v1.Id < vBetween.Id AND vBetween.Id < v2.Id AND v1.ChangeDate <= vBetween.ChangeDate AND vBetween.ChangeDate <= v2.ChangeDateWHERE vBetween.Id IS NULLORDER BY v1.ChangeDate; Which, when auditing this series of changes:

UPDATE dbo.Users SET AboutMe = 'Update Numero Uno' WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = NULL WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = 'Update Part 3' WHERE Id = 26837;DELETE dbo.Users WHERE Id = 26837; Comes up with these results:

Notice how rows 2 & 3 both have nulls for the v2 and Current columns, but they have different results for AboutMe_After? That’s because the 2nd update statement actually did set AboutMe to NULL, and we do have a Users_Change row that knows about it (from Users_Change_Id = 3.)

In production, if I was faced with this problem, I’d probably want to change the trigger itself to log deleted rows as well as updated ones. However, I found this to be a really fun exercise because I was faced with this exact problem at a client – we were auditing past data whose changes had already been made, and I couldn’t build the historical data retroactively after the changes had been made.

View Details

I was chatting with a client’s DBA about this thought-provoking blog post about data governance in the age of generative AI. The DBA’s concern was, “What if we hook up generative AI tools to the production database, and someone asks for, say, recommended salary ranges for our next CEO based on the current CEO’s salary? Will the AI tool basically bypass our row-level security and give the querying person information that they shouldn’t be allowed to see?”

And she had a really good point.

If you haven’t worked with AI tools yet, I don’t blame you. You’ve got a real job, dear reader, unlike me who’s just a consultant who gets to travel all over the world while reading cool blog posts on planes. Anyhoo, since I get to play around a lot more, I’ll give you a quick recap:

  • Large language models (LLMs) like ChatGPT take plain English requests and turn them into results
  • Those results aren’t just text: they can include tables of results, scripts with T-SQL commands, or JSON files
  • The LLMs are trained on publicly available data
  • You can enhance their training by providing additional data, like the contents of your file shares and databases
  • There’s almost zero security on LLM requests and result sets

So the scenario that scares the hell out of me is:

  • A power user signs up for an LLM service or runs one on their computer
  • The power user wants better results, so they provide additional training data: they point the LLM at the company’s data set and load it with financial results, customer info, employee salaries, etc
  • The power user loves the report results, so they give other people access to the LLM

And the end result is that anyone who queries the LLM suddenly has access to everything that the power user had access to at the time of the LLM training. Anyone with access to the LLM might ask for a list of customers, employee salaries, or whatever.

Me, as pictured by CopilotThat would be what we call “bad.”

Sure, in a sense, this is the same problem data professionals have been struggling with for decades: people can export data, and once it’s out of the database, we don’t have control over who gets to see it. This isn’t new. It’s been the same story ever since Larry Tesler invented copy/paste.

But what’s new is that large language models:

  • Don’t make it clear where their data comes from
  • Aren’t easily reverse-engineered
  • Have damn near zero security on inputs and outputs

So now, the Amazon blog post explains why smart people are going to burn cycles reinventing row-level security. I’m not saying the blog post is bad – it’s not! It’s just a damn shame that the next 10-20 years of data governance are going to look exactly like the last 10-20 years of data governance.

Spoiler alert: we’ve sucked at this kind of security for decades, and we will in the next decade, too.

View Details

Historically, Microsoft publicly announces the next version of SQL Server about a year before it ships. For example:

  • November 2, 2021, Microsoft announced the private preview of SQL Server 2022.
  • About 6 months later, on May 24, 2022, they announced the public preview.
  • About 12 months after the private preview announcement, on November 16, 2022, SQL Server 2022 was generally available.

This was pretty consistent with past releases: about a year before the release, Microsoft would go on record with the features included with the next version, and some companies would be able to start using it in production to prepare for the eventual release.

Well, it’s been about 2.5 years since SQL Server 2022’s announcement, so we’re looking at at least a 3-year release cycle. We might be coming up on the announcements for SQL Server 2025.

They could either announce the next version’s features at Microsoft Build on May 21-24 or at the PASS Summit on Nov 4-8. I’ll be watching the Build session catalog as Microsoft updates it because when Microsoft announces a new product, the related sessions are hidden until after the product is officially announced. It’s free to attend Build online, so if they announce 2025 during a keynote, I’ll tune in to the related general sessions.

I personally love a 3-year release cadence, and I don’t want new versions any more frequently than that. People have a hard time upgrading, and frankly, Microsoft has a hard time shipping that quickly. Just release every 3 years, and make sure the product is actually ready at the time of release. That’s good enough.

I’ve heard some folks say, “Maybe Microsoft is done with SQL Server because they want everyone to move to Azure.” Well, I’m sure they do, but they also acknowledge the reality that many companies host their infrastructure in Amazon and Google. Those clients need SQL Server licensing, because you can’t practically run Azure SQL DB in other clouds.

Microsoft also has to keep releasing new versions of SQL Server because they need to keep cashing your sweet, sweet Software Assurance checks. While SA does come with other benefits, like free licensing for a couple/few passive standby servers for HA and DR, those benefits aren’t priceless. If Microsoft didn’t ship a new version for, say, 5 years, I know some companies that would simply stop paying Software Assurance. Even if these companies don’t actually upgrade that often, they pay for the ability to know that they could upgrade – which means Microsoft has to keep bringing out versions & features.

What might Microsoft add in 2025? Clearly, AI is the buzzword du jour, and Microsoft’s Joe Sack has already demoed some of the Copilot things they’re working on in Azure SQL DB. Copilot integration requires internet connectivity, something that’s easier to integrate in cloud databases like Azure SQL DB. If you try to do large language model work on-premises, you’ll quickly learn that it’s extremely CPU and GPU intensive, and that doesn’t really make sense for a product like SQL Server that’s licensed by the CPU core. I’ll be curious to see how they package AI services to a crowd that sometimes screams in horror at the idea of giving their database servers access to the Internet.

Would you be okay giving your SQL Servers access to the Internet? And what AI-related features would you love to see included?

View Details

Your challenge for this week was to find out who keeps mangling the contents of the AboutMe column in the Stack Overflow database.

Conceptually, there are a lot of ways we can track when data changes: Change Tracking, Change Data Capture, temporal tables, auditing, and I’m sure I’m missing more. But for me, there are a couple of key concerns when we need to track specific changes in a high-throughput environment:

  • I need to capture the login, app name, and host name that made the change
  • I need to capture a subset of table columns, not all
  • I need to capture a subset of the before & after changes, not all

For example, in this week’s query challenge, the Users table has a lot of really hot columns that change constantly, like LastAccessDate, Reputation, DownVotes, UpVotes, and Views. I don’t want to log those changes at all, and I don’t want my logging to slow down the updates of those columns.

Furthermore, I probably don’t even want to capture the entire before or after values of the AboutMe column, either. It’s NVARCHAR(MAX), which can be huge. Depending on what “mangling” means, I might only need to grab the first 100 characters, or the length of the before/after changes. That’ll reduce how much I store, too, important in high-transaction environments that push the data to several Availability Group replicas.

Let’s say here’s the data I decided to gather:

CREATE TABLE dbo.Users\_Changes(Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, UserId INT NOT NULL, ChangeDate DATETIME2, AboutMe\_Before NVARCHAR(100), AboutMe\_After NVARCHAR(100), AboutMe\_Length\_Before BIGINT, AboutMe\_Length\_After BIGINT, HostName NVARCHAR(128), AppName NVARCHAR(128), SystemUser NVARCHAR(128))GO You could refine that further by capturing less data if you knew exactly how the data was being mangled. For example, if the mangler always sets the rows to null or to short strings, you wouldn’t have to gather the before/after contents – just the length would be enough.

You could also get a little fancier by only storing the “before” data, but I kept it simple and just logged both before & after here for simplicity’s sake. (Spoiler alert: the next Query Exercise at the end of this post is going to be a related challenge.)

To populate this data, I love triggers. Here’s the one I came up with after a little testing:

CREATE OR ALTER TRIGGER dbo.Users\_Update\_Audit ON dbo.Users AFTER UPDATE ASBEGINSET NOCOUNT ON;INSERT INTO dbo.Users\_Changes (UserId, ChangeDate, AboutMe\_Before, AboutMe\_After,AboutMe\_Length\_Before, AboutMe\_Length\_After,HostName, AppName, SystemUser)SELECT i.Id, GETDATE(),LEFT(d.AboutMe, 100), LEFT(i.AboutMe, 100),LEN(COALESCE(d.AboutMe,'')), LEN(COALESCE(i.AboutMe,'')),HOST\_NAME(), APP\_NAME(), SYSTEM\_USERFROM inserted iINNER JOIN deleted d ON i.Id = d.IdWHERE COALESCE(i.AboutMe,'') <> COALESCE(d.AboutMe,'')ENDGO The actual query plan on an update is nice and quick. A few things about the code that may not be intuitively obvious:

  • I didn’t use the UPDATE() function because it doesn’t handle multi-row changes accurately
  • The SET NOCOUNT ON stops the trigger from reporting back the number of rows affected by the insert, which can break apps that weren’t expecting to see multiple messages back about how many rows just got inserted/updated
  • The COALESCEs in the WHERE are to handle situations where someone sets the AboutMe to null (or changes it from null to populated)
  • The COALESCEs in the SELECT are to properly set the length columns to 0 when the AboutMe is null
  • I only fire the trigger on updates, not inserts or deletes, because the business request was about mangling existing AboutMe data

If you knew the exact kind of mangling that was happening, you could refine the WHERE clause even further, looking for specific data patterns.

Here’s what the output table contents look like after changing a few rows:

Nice and simple, and makes for really easy investigations. Just make sure to drop the trigger and the change table when you’re done! I had a really hearty laugh at one client when I returned a year later and they still had both in place.

Other SolutionsTom aka Zikato aka StraightforwardSQL commented with a pointer to an awesome blog post he’s written on this very topic! He compared & contrasted a few different solutions, and then ended up with a hybrid solution involving a trigger, XE, and Query Store.

Connor O’Shea wrote an extended events session that filters query text based on its literal contents. I get a little nervous about that kind of thing, because they often miss weirdo situations (like synonyms and aliases), and they’re a little tricky to debug. For example, his first iteration also caught selects – something that would be terrible on a production system. It’s a good starting point though.

Erik Darling used temporal tables to capture the changes, and I especially love his security disclaimer. I don’t have any experience with login impersonation either – it’s funny, but my contract actually prohibits any security work whatsoever. I hate security work.

ChatGPT is helpful for tasks like this, even for a starting point if you don’t end up actually using the code. I asked ChatGPT to do this for me, and it came up with different results, but a good starting point nonetheless.

Your Next Query Challenge:Getting Data Out of a Fancier TriggerThe above process works great if we’re willing to store both the before AND after values, but what if we’re dealing with a really high-throughput system with a ton of changes per second, and we want to avoid storing the “after” values each time? The table & triggers would look like this:

DROP TABLE IF EXISTS dbo.Users\_Changes;GOCREATE TABLE dbo.Users\_Changes(Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, UserId INT NOT NULL, ChangeDate DATETIME2, AboutMe\_Before NVARCHAR(100), AboutMe\_Length\_Before BIGINT, HostName NVARCHAR(128), AppName NVARCHAR(128), SystemUser NVARCHAR(128))GOCREATE OR ALTER TRIGGER dbo.Users\_Update\_Audit ON dbo.Users AFTER UPDATE ASBEGINSET NOCOUNT ON;INSERT INTO dbo.Users\_Changes (UserId, ChangeDate, AboutMe\_Before, AboutMe\_Length\_Before,HostName, AppName, SystemUser)SELECT i.Id, GETDATE(),LEFT(d.AboutMe, 100), LEN(COALESCE(d.AboutMe,'')),HOST\_NAME(), APP\_NAME(), SYSTEM\_USERFROM inserted iINNER JOIN deleted d ON i.Id = d.IdWHERE COALESCE(i.AboutMe,'') <> COALESCE(d.AboutMe,'')ENDGO Now, when we want to get data out to see the before & after values, it gets a little trickier. Say we run 3 update statements, and then check the value of the change table:

UPDATE dbo.Users SET AboutMe = 'Update Numero Uno' WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = NULL WHERE Id = 26837;UPDATE dbo.Users SET AboutMe = 'Update Part 3' WHERE Id = 26837;SELECT * FROM dbo.Users\_Changes; The resulting query only shows the before data, but not the change that was actually affected during that update statement:

For example, notice that the last update above set the contents to Update Part 3, but that value doesn’t show in the screenshot. That’s your challenge: I want you to write a SELECT query that reproduces the full before & after data for each change, like the earlier query from the blog post:

Share your answer in the comments, and feel free to put your queries in a Github Gist, and include that link in your comments. I’ll check back in next week with answers & thoughts. Have fun!

View Details

The short story: SQL Server 2019 appears poised to swallow the SQL Server market altogether, hahaha.

The long story: ever wonder how fast people are adopting new versions of SQL Server, or what’s “normal” out there for SQL Server adoption rates? Let’s find out in the winter 2023 version of our SQL ConstantCare® population report.

Out of the thousands of monitored SQL Servers, SQL Server 2019 is now at 48% of the market! That’s the highest percentage we’ve seen for any version in the 3 years that we’ve been doing this analysis, up from last quarter’s 44% market share. Here’s how adoption is trending over time, with the most recent data at the right:

SQL Server 2019 still continues to grow while everything else shrinks, with the exception of 2022 treading water:

  • SQL Server 2022: 7%, up from 5% last quarter
  • SQL Server 2019: 49%, holding pretty steady
  • SQL Server 2017: 15%, holding steady
  • SQL Server 2016: 18%, down from 22%
  • SQL Server 2014: 6%, steady – and goes out of support in just 2 months!
  • SQL Server 2012 & prior: 4%
  • Azure SQL DB and Managed Instances: 1%
  • New metric this month: 4% of the SQL Servers here are Amazon RDS. They’re included in the SQL Server 2019/2017/2016 metrics above, since they’re technically part of those crowds.

How big are typical SQL Servers?Let’s group the market together roughly into quarters:

For a long time in the SQL Server space, people have used the term VLDB to denote a very large database, and we’ve usually marked 1TB as the town borders of VLDBville. Today, given that about 1/4 of all SQL Servers host 1TB or more, and given how fast modern storage is able to back up 1TB databases, that 1TB threshold is less meaningful.

That large number of small servers means the CPU distribution is also fairly small:

As is the memory target distribution:

Although if you slice & dice by data size, then that changes the CPU & memory numbers differently. The number of CPU cores people typically use for >3TB SQL Servers is very different than the core count for, say, 50-250GB servers. And now if you’ll excuse me, I gotta do a whole bunch of slicing and dicing because I share that data with clients when we’re analyzing their SQL Servers during a SQL Critical Care®.

View Details

Back at home in the office, time to settle in with a nice caffeine-free Diet Coke and go through your top-voted questions from https://pollgab.com/room/brento. Why caffeine-free? Because I slug multiple coffees first thing in the morning when I wake up (usually around 3am-4am), and by the time I stream with y’all, I don’t need any more go juice.

Here’s what we covered:

  • 00:00 Start
  • 02:30 MyTeaGotCold: Has your opinion of Lock Pages in Memory changed over the past 10 years?
  • 03:48 MustangKirby: How can I check what data or pages are in cache? I woke up last night wondering if data I’m writing takes up cache memory.
  • 05:50 DBADoug: Why is SELECT INTO faster than INSERT INTO (of the same exact schema) with no indexes? When testing I notice about 9x more time on the “Table Insert” block in the plan) when the table is pre-defined.
  • 06:30 John R: Does SQL Server 2014+ have stored proc execution plans by user/spid? We saw 1 stored proc get slow for just 1 user (timing out after 30 sec, but 300ms for other users). Once stats were updated, stored proc was fast for that user again. I
  • 07:31 DemandingBrentsAttention: Does order of “include” index columns matter, like it does for key columns?
  • 08:40 Newtopg: Hi Brent , are there any tools You recommend for MSSQL to PostgreSQL migration ? Any open source tool that does both schema and data migration ? We are testing Pgloader and wanted your opinion on if there is any popular tool you recommend free or paid . Thank you
  • 09:36 GrumpyOldMan: I have a query that is causing a lot of blocking. SQL is recommending an index, which I agree should be used. Problem is, index already exists, exact index that SQL is recommending, but not being used. What’s up with this?
  • 10:35 bamdba: PowerShell for SQL Server? Love T-SQL & its effectiveness, but surprised by PowerShell’s popularity. Am I missing automation & scripting benefits?
  • 11:30 Sergio B: Can the tools sp_blitz and especially sp_BlitzWho capture the statements executed with sp_executesql?
  • 11:45 Chris Blain: I recently rebuilt indexes with compression. If I take a full backup, and logs, and restore to a brand new instance, will the restored database’s indexes have compression applied, or will I have to manually run the “alter index ” again on each one to apply data compression?
  • 12:35 Chris Blain: We have a database that is a single partition, some of the tables specify TEXTIMAGE_ON [PRIMARY]. this is stopping applying data_compression to the indexes. is it needed? if it was removed, could it cause issues for the underlying table, could I then apply index compression?
  • 13:13 SickieServer: Have you ever encountered databases (that maybe have been in service for decades) where the queries, while potentially fixable, are so numerous, and so bad, that the only practical solution is for the organisation to license more cores and buy more RAM?
  • 16:30 Gustav: What’s your opinion of the new regex support in Azure SQL DB? Will we see this flow down to canned SQL Server?
  • 18:33 I’m a potato ?: What’s different from Hong Kongs Databases to the rest of the world?
  • 23:06 Miles: Hi Brent,while tuning queries, which ones to be tuned first? is it high logical reads queries or high cpu queries or high duration queries? which one to be focused first?

View Details

Is your company hiring for a database position as of May 2024? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

For this week’s Query Exercise, your challenge is to find out who keeps messing up the rows in the Users table.

Take any size version of the Stack Overflow database, and the Users table looks like this:

People are complaining that from time to time, the contents of the AboutMe column in some – but not all – of the Users rows are getting mangled. We’re not sure if it’s an app bug, an ETL problem, or someone goofing around in T-SQL, and we need you to find out.

At the same time, this is also a busy production database, and we want to minimize impacts to the end users. The site still needs to go fast.

For this exercise, I’m not expecting a specific “right” or “wrong” answer – instead, for this one, you’re probably going to have a good time sharing your answer in the comments, and comparing your answer to that of others. Feel free to put your queries in a Github Gist, and include that link in your comments. I’ll check back in next week with the approach I usually use with clients. Have fun!

View Details

I first registered BrentOzar.com way back in May 2001.

Over the years, some things in databases have changed a lot, but some things still remain the same.

Every year, people get handed applications and databases, and they’re told, “The back end is Microsoft SQL Server. Figure it out and make it work – faster.”

Every year, people struggle. They try to learn as much as they can via Google, free blog posts and webcasts, and their peers. They put the pieces together as best they can, but eventually, they hit a wall.

And that’s where my classes come in.

Fundamentals, Yearly$195Save $200* Fundamentals classes

Sign upFundamentals, Lifetime$395Save $300* Fundamentals classes * Buy-now-pay-later available

Sign upFundamentals + Mastering, Yearly$995Save $300* Fundamentals classes * Mastering classes

Sign upThe sale ends May 31. To get these deals, you have to check out online through our e-commerce site by clicking the buttons above. During the checkout process, you’ll be offered the choice of a credit card or buy now pay later.

Can we pay via bank transfer, check, or purchase order? Yes, but only for 10 or more seats for the same package, and payment must be received before the sale ends. Email us at Help@BrentOzar.com with the package you want to buy and the number of seats, and we can generate a quote to include with your check or wire. Make your check payable to Brent Ozar Unlimited and mail it to 9450 SW Gemini Drive, ECM #45779, Beaverton, OR 97008. Your payment must be received before we activate your training, and must be received before the sale ends. Payments received after the sale ends will not be honored. We do not accept POs as payment unless they are also accompanied with a check. For a W9 form: https://downloads.brentozar.com/w9.pdf

Can we send you a form to fill out? No, to keep costs low during these sales, we don’t do any manual paperwork. To get these awesome prices, you’ll need to check out through the site and use the automatically generated PDF invoice/receipt that gets sent to you via email about 15-30 minutes after your purchase finishes. If you absolutely need us to fill out paperwork or generate a quote, we’d be happy to do it at our regular (non-sale) prices – email us at Help@BrentOzar.com.

View Details

On November 4 in Seattle, I’m presenting a new pre-conference workshop!

Tuning T-SQL for SQL Server 2019 and 2022

You’ve been working with SQL Server for a few years, and you’re comfortable writing queries and reading execution plans.

Your company is now using SQL Server 2019 or 2022 in production, and you want your queries to go as fast as possible. You want to know what changes to make to your existing queries in order to speed them up dramatically. You don’t want a “what’s new” session – you want practical information you can use to identify T-SQL that used to work fine in older versions, but now needs attention in newer versions.

In this 1-day session, Brent Ozar will use the same practical before-and-after techniques that he uses in his Query Challenges blog series in order to demonstrate what parts of your skills need to change as you modernize your databases.

You should be comfortable using SSMS to write multi-page queries, functions, and stored procedures. You should be comfortable identifying common query plan operators like index seeks & scans, key lookups, sorts, and parallelism, and comparing plans.

In this session, you’ll:

  • Learn what kinds T-SQL should be rewritten to aim for batch mode
  • Understand the effects of cardinality estimation feedback & parallelism feedback, and how to improve them
  • Discover new monitoring potential in query plan DMVs to troubleshoot bad plans and blocking

Attendees will get one year free access to my Fundamentals of Query Tuning and Mastering Query Tuning classes, both of which will be updated with content from the pre-con.

Register here, and see you in Seattle!

View Details

As my time in Hong Kong came to an end, I sat inside on a foggy morning and hit your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 01:32 MyTeaGotCold: Are there any signs of brain drain from SQL Server to Postgres? It seems that every SQL Server guru agrees that Postgres is better, even if SQL Server pays them more.
  • 02:33 Frozt: Do you have a checklist on decommissioning an SQL Server?
  • 03:06 Mike: Hi Brent, you mentioned that you are going to update Recorded Classes in 2024. Is this still true ? If yes, which ones you want to update, and when to expect that ?
  • 03:38 Mike: We know Read Committed is default isolation level, and locks are taken on statement level. What happens when you issue Begin Transaction, and then run many SQL statements before Commit ? Isolation level changes during the explicit transaction ? If yes, to which one ?
  • 04:49 RoJo: if a nightly CheckDB fails, how do I approach recovery or validating data? Would it be certain pages / tables? Must I simply roll back to last known good CheckDB ?
  • 05:33 Eugene Meidinger: If I wanted to run the Stack Overflow database as a homelab on a laptop, what specs would you recommend?
  • 06:22 Justin M: Are you a Biphasic sleeper? What is your optimal nap time and length?
  • 07:10 DataBarbieAdministrator: Could you create a blog series on well-known SQL Server Best Practices that are now outdated, explaining why and any alternatives? That would be useful and absolutely interesting! Thanks for your great job for the community!
  • 08:06 Fermin: Hi Brent, just want to know what do you think about the career path future for DBAs. Are we moving to a modern Full Stack or Data Engineer? Thanks.
  • 08:48 corelevel: Hey Brent! In your opinion, what is the minimum table size (in pages) to start adding indexes to it?
  • 09:48 ChompingBits: How many of your customers are using Kerberos for authentication vs SPNs on NTLMv2 or lower? The latter is a pain to configure, and often leads to users/devs running scripts from the SQL server when one more servers are connected to in the query.
  • 10:04 Jonathan: What do you recommend for the number of databases/size on a single disk? I’ve always just ballparked around keeping 2TB per drive and spinning up a new drive when that one fills, but lately we’ve had smaller dbs that have a lot of I/O and larger dbs with less users, etc. Thanks!
  • 11:27 Miles: How important archiving data is? We see history tables growing from GBs to TBs.What problems we might run into if we don’t archive the old data. App team hesitant due to potential data requests from other teams. Any advise on balancing data retention needs with perf optimization?
  • 12:47 Miles: When there’s blocking, app team asks what lock caused blocking. Is it okay to collect lock info or is it overwhelming. sp_whoisactive runs very slow with get_locks =1. Are we doing right thing collecting lock info or should be focusing on something else like tuning head blocker?
  • 13:37 SteveE: Hi Brent, Is there ever a use case to have a Non Clustered index created on the clustering key, perhaps when the table is a wide table?
  • 14:34 Gustav: What’s your opinion of copilot for Azure SQL DB?
  • 15:35 Steve E: Hi Brent We have a query which runs daily that inserts a recursive CTE into a table. Our monitoring tool shows the plan changes each time as it has a different plan handle but all the plans have the same plan hash. What would cause the difference in the plan handle?
  • 16:39 ganesh: Hello Sir, Using excel source in ssis , error : there are XXX bytes of physical memory with XXXX bytes free. system reports 98% memory load.tried autobuffer in data flow ,rows per batch at destination, reduce columns size from navchar255-nvarchar 25 -30 .how to avoid error
  • 16:58 Jim Johnston: I’m thru half of the Brent Ozar Season pass bundle, but looking for guidance with excessive context switching in SQL server. If its in the bundle, can I get a link to where can find it to review this?
  • 17:53 Nintenbob: Do you have any experience/thoughts on using SQL Server 2019’s UTF-8 collation support for varchar as an alternative to nvarchar? At the surface level it seems a clear improvement for most uses that need unicode, but not sure if there are hidden downsides.
  • 18:46 Moctezuma DBA: I was recently told index rebuild removes the 14-byte version control pointer. When index rebuild makes sense, should we set FILLFACTOR less than 100% to make room for those values and then mitigate page splits for that 14-byte pointer addition at each row?
  • 19:23 ProdDBA: Storage for big data, what options are there for maintaining large databases over time without archiving? Splitting the large databases onto their own drives? Just buying more storage? Ideas on how to ask others in big data how they manage their database storage?

View Details

I’m kinda weird. I get excited when I’m troubleshooting a SQL Server problem, and I keep hitting walls.

I’ll give you an example. A client came to me because they were struggling with sporadic performance problems in Azure SQL DB, and nothing seemed to make sense:

  • sp_BlitzFirst @SinceStartup = 1 showed very clearly that their top wait, by a long shot, was blocking. Hundreds of hours of it in a week.
  • sp_BlitzIndex showed the “Aggressive Indexes” warning on a single table, but… only tens of minutes of locking, nowhere near the level the database was seeing overall.
  • sp_BlitzCache @SortOrder = ‘duration’ showed a couple queries with the “Long Running, Low CPU” warning, and they did indeed have blocking involved, but … pretty minor stuff. Plus, their plan cache was nearly useless due to a ton of unparameterized queries pouring through constantly, overwhelming Azure SQL DB’s limited plan cache.
  • sp_Blitz wasn’t reporting any deadlocks, either. (sp_BlitzLock doesn’t work in Azure SQL DB at the moment because Microsoft’s no longer running the default system health XE session up there. They turned that off in order to save money on hosting costs, and passed the savings on to… wait… hmm)
  • As a last-ditch hail-Mary, I ran sp_BlitzWho repeatedly, trying to catch the blocking happening in action. No dice – the odds that I’d catch it live weren’t great anyway.

During a bio break, I unloaded the dishwasher (it’s what I do) and made a mental list of things that would cause blocking, but not on indexes, and not show up in the plan cache. And that’s when it hit me, just as I was unloading the wine glasses. (Don’t judge me: I drink a lot, and I don’t have time for hand-washing.)

sp_getapplock lets developers use SQL Server’s locking mechanisms for their own purposes, unrelated to tables. Let’s say you have an ETL process, and you want to make sure that it can only be run from one session at a time. You’d start the process by running:

EXEC sp\_getapplock @Resource = 'ETL Process',@LockMode = 'exclusive',@LockOwner = 'session' That’s kinda like saying BEGIN TRAN, but for entire processes. If someone else tries to run the same query and grab a lock from their session, they’ll get blocked. Here’s what it looks like from sp_BlitzWho:

Session 63 grabbed the lock first, and session 70 is trying to get it, but they’re waiting on LCK_M_X because 63 has an eXclusive lock on it. Note that 63’s query_text shows sp_getapplock – that’s where the troubleshooting Eureka moment hits.

When session 63 is done, it can release the lock like this:

EXEC sp\_releaseapplock@Resource = 'ETL Process',@LockOwner = 'session' If you work like I do, troubleshooting things after they’ve happened, without the ability to set things up in advance of the problem, this is extraordinarily hard to track down.

Once you know about the problem, you can monitor blocked processes in Azure SQL DB (shout out to Etienne Lopes for a well-written, start-to-finish tutorial, and you should subscribe to his blog.) Etienne uses a file target there, but I used a ring buffer target because I didn’t have access to the client’s Azure file systems. The ring buffer target is way easier to set up:

CREATE EVENT SESSION [BlockedProcesses] ON DATABASEADD EVENT sqlserver.blocked\_process\_report()ADD TARGET package0.ring\_buffer(SET max\_memory=(10240))WITH (STARTUP\_STATE=ON)GOALTER EVENT SESSION [BlockedProcesses] ON DATABASE STATE = START;GO The problem is that Azure SQL DB’s blocked process threshold is 20 seconds, and can’t be changed. For high-volume, short-duration blocking, you’ll be better off rapidly running sp_BlitzWho and logging it to table:

EXEC sp\_BlitzWho@OutputDatabaseName = 'mydbname',@OutputSchemaName = 'dbo',@OutputTableName = 'BlitzWho' Once you’ve identified that there’s a blocking chain led by sp_getapplock, the database side of the tuning work is done. There’s no database-side “tuning” on blocking like this: it’s up to the developers to use conventional transaction-based tuning processes, but in whatever app code is calling sp_getapplock. The app is essentially running its own transaction, so the developers need to:

  • Minimize the setup work done inside the transaction: do all set-up work like fetching config data ahead of time, before the transaction starts
  • Minimize post-processing work inside the transaction: do logging later, after releasing the lock
  • Minimize row-by-row processing: do work in sets, touching each table as few times as possible, not row-by-row inserts/updates/deletes
  • Minimize round trips between the app server and database server: ideally, prepare everything as a package and send it off to a stored procedure to do all the committing quickly, eliminating all round trips (and then rip out sp_getapplock while you’re at it)

With those tips, sp_getapplock can be completely fine. It’s not like sp_getapplock is inherently bad, any more than BEGIN TRAN is bad. It’s just that detecting its long transactions is way harder.

View Details

The Monday after next, I’ll be getting together with dozens of smart people who are a lot like you. You’ve attended some of my free online streams, read my blog posts, and you use the First Responder Kit. You enjoy my laid-back, humorous approach to sharing what I’ve learned over the years.

You love live classes. You’ve tried watching recordings or stepping through demos yourself, but…you just can’t block out the time, and you can’t stay motivated while you’re watching a recording. You like the fast-paced energy of seeing me live, asking me questions, and seeing me respond to your chats.

You hate free conferences that feel like Zoom meetings. You’ve tried attending a few online events, but they felt just like sitting through one meeting after another. They didn’t dive deeply into any one subject – they just hopped around from one topic to another, and many of those topics just weren’t relevant to you. They were good for free stuff, but…

You’re ready for Fundamentals Week! You’ll spend the week with me learning about indexes, query tuning, columnstore, how I use the First Responder Kit, and more.

The conference dates are May 6-10, 2024, and classes are 10AM-6PM Eastern, 7AM-3PM Pacific. Here’s what we’ll cover:

  • Monday: How I Use the First Responder Kit
  • Tuesday: Fundamentals of Index Tuning
  • Wednesday: Fundamentals of Query Tuning
  • Thursday: Fundamentals of Columnstore
  • Friday: Fundamentals of TempDB

Register now for $1,595. To keep prices low, this price does not include the class recordings. If you want those, during checkout, you’ll see an offer to add lifetime access to my Recorded Class Season Pass Fundamentals for just $395. See you in class!

View Details

I recently went to Shanghai & Hong Kong, and stopped to take your questions from https://pollgab.com/room/brento while sitting next to the Hong Kong harbor.

Here’s what we covered:

  • 00:00 Start
  • 01:18 Jason G – RN & Accidental DBA: Would you elaborate on DB Owner implications? sp_Blitz help recommends using the SA account, but the articles referenced by Andreas Wolter advocate for using low privileged accounts which are DB specific. Which would you recommend and why?
  • 02:44 MyTeaGotCold: Can you name any good relational databases that aren’t built around SQL? It’s strange that a system so old is still the best.
  • 03:58 John: Hello Brent. Is SQL Server 2022 ready for production/prime time and more more huge bugs/issues? Asking due to last blog post was in 2023 on that particular topic. Thanks.
  • 04:57 Chicago Joe: Is there a trend to move database access to API only? I am asking because we are moving to next version of ERP and our CIO has told database developers that only access to new database will be through a Web API. Database is still on prem on next version, too.
  • 06:23 J. Fisher: Hey Brent, Are you able to comment/explain SQL Server “Native” Geography/Geometry datatypes, other CLR stuff, and how they can use and exhaust “App Domain” memory… leading to “Unloading due to memory pressure”… Can’t “afford” to keep adding memory.
  • 08:19 Steve E: Hi Brent, Is there a way to assess overall reads per table across a workload in an attempt to see which tables we might want to focus our index tuning efforts to? Eg if the Posts table has 90% of the overall workload reads, we would probably want to start our index tuning there.
  • 09:29 neil: dev thinks “azure” will solve all their problems. (they dont understand we’re already sql on azure vm). they’re committing all the same mistakes that created disasters on-prem. what surprises are they in for ?
  • 11:12 Dream catcher: What time do you like to go-to bed and wake up? Do you nap after lunch?
  • 11:43 ChompingBits: What do you think is nominally the difference between ADF and SSMS? ADF has query plans and access to many of the admin tools and reports in SSMS. How long do you think Microsoft will continue to offer both tools.
  • 12:45 gringomalbec: Hi Brent, we realize you recommend not using Linked Servers to connect to other MS SQL Servers. But my friend asks if you find ok using Linked Servers to download data from sources other than MS SQL Server that cannot be connected directly in SSMS using Database Engine ?

View Details

Post your Azure SQL DB and SQL Server questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me discuss. In this episode, I’m overlooking Breiðamerkursandur, Diamond Beach, one of the most Instagrammed places in Iceland. Here’s a shot from a prior trip when I climbed up on one of the icebergs: This time...

View Details

I got an interesting request for consulting, and I’m going to paraphrase it: We were using Azure SQL DB with automatic index tuning enabled for months. Things were going great, but… we just deployed a new version of our code. Our deployment tool made the database schema match our source control, which… dropped the indexes...

View Details

Pinal Dave recently ignited a storm of controversy when he quizzed readers about which one of these would be faster on AdventureWorks2019: [crayon-64feb6666bf59548644264/] I laughed so hard when I saw the storm of responses on Twitter. People sure do get passionate about this kind of thing. If you ever wanna witness patience and generosity in...

View Details

Post your Azure SQL DB and SQL Server questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me discuss. In this episode, I’m at Jökulsárlón Glacial Lagoon, a wonder of nature, watching the icebergs pile up, stuck in the lagoon due to the incoming high tides.

Here’s what we covered:

  • 00:00 Start
  • 01:15 Oli-the-dba: I hear “clustering is dumb and complex” on azure IaaS all the time from non dbas. One can only assume they hate HA/DR. However, Have you had any clients go clusterless ?
  • 03:14 Ozan: Hi Brent, do you prefer to access external data via linked server or if possible via polybase? What is your experience with polybase? Thanks
  • 04:01 Jag B: When avoiding blocking, is READPAST hint better than NOLOCK?
  • 04:50 Xavier P: What are the top issues your clients run into when deploying Power BI Gateway?
  • 05:37 Jerry Mathers: What is your opinion of DBeaver (
  • https://dbeaver.io/) for working with SQL Server VM and Azure SQL?
  • 06:22 Wally: Should Azure drives that host SQL VM data files be formatted with 4k, 8k, or 64k block size?
  • 07:29 Shehroz Sabzwari: During the building / installing of a new SQL Server instance, when should you run sp_blitz?
  • 08:21 Oli-the-dba: Hi Brent, do you see a use case for Azure PaaS if you have a team of 4 experienced dba’s. I’m at a 500 server shop about to embark on our azure journey, performance preferred over cost savings.
  • 09:25 Analyse T: Do RPO/RTO numbers usually improve when migrating from Log Shipping to Always On Availability Groups?
  • 10:25 Mahtab Keramati: What test apps do you like to run on prospective new SQL VM Hosts for CPU, Network, and Disk performance?
  • 11:06 Izzy G: Enjoy how you relate technical problems to every day experiences. Did you have to learn this or does it come naturally?

View Details

Road trip time! I’m recovering from jet lag after flying over to Iceland, so I went through your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:55 Shehroz Sabzwari: What are your pros / cons for running on-prem SQL Server in a VM versus bare metal?
  • 02:04 adba: what are your recommendations for windows performance plan for sql server running on a VM. My private cloud vendor says it is not required to be set to high performance.
  • 03:25 Holy: Can’t you agree that all RDBMS databases are approaching their limits, just as ISAM databases did in the 1980s and 1990s?
  • 05:47 sandimschuh: Hi Brent, is it always safe to change the database setting from Read Committed to RCSI? What kind of queries or query patterns will be negatively affected by this change?
  • 07:04 Mike Conrad: Hi Brent, My team uses system versioned tables a lot. Our ORM, EFcore, sometimes will write updates that don’t change any data, but this does generate a new HISTORY table row, bloating our audit trail. Are instead of triggers a viable way to prevent this?

View Details

Is your company hiring for a database position as of September 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

On August 30, Azure’s Australia East data center had a big problem, affecting customers like Bank of Queensland and Jetstar. Here’s the timeline:

  • 30 August 2023 @ 08:41 – Voltage sag occurred on utility power line
  • 30 August 2023 @ 08:43 – Five chillers failed to restart
  • 30 August 2023 @ 10:30 – Storage and SQL alerted by monitors about failure rates
  • 30 August 2023 @ 10:57 – Cosmos DB Initial impact detected via monitoring
  • 30 August 2023 @ 11:15 – Attempts to stabilize the five chillers were unsuccessful after multiple chiller restarts
  • 30 August 2023 @ 11:34 – Decision was made to shutdown infrastructure in the two affected data halls
  • 30 August 2023 @ 20:29 – All but two SQL nodes recovered
  • 31 August 2023 @ 04:04 – Restoration of Cosmos DB accounts to Australia East initiated
  • 31 August 2023 @ 04:43 – Final Cosmos DB cluster recovered, restoring all traffic for accounts that were not failed over
  • 31 August 2023 @ 08:45 – All external customer accounts back online and operating from Australia

Note that 11:34, the decision was made to shut down infrastructure without Microsoft failing your databases over elsewhere. If you were an Azure SQL DB or Cosmos DB user, and you weren’t paying for replicas in another data center, it was up to you to follow Microsoft’s disaster recovery guidance.

Controversial opinion: I actually love that and I think it’s great.

I see a lot of Azure SQL DB users make the mistake of assuming that Azure includes disaster recovery, but it does not. It’s on you, and as a result, you save money. (Same thing in AWS Aurora PostgreSQL.) I’m sure there are plenty of small business databases that don’t need disaster recovery within a day or two. Heck, even Bank of Queensland probably has some databases that fit into that category, although… probably not as many as actually went down, hahaha.

There’s a problem with that, though: Microsoft didn’t notify affected customers about which of their databases were down, or that the customers should start their DR processes. Microsoft couldn’t notify customers because … they didn’t know who those customers were. Microsoft’s Azure status history doesn’t let you easily link to a single event, but if you expand the outage on 30 Aug, the preliminary writeup is really detailed, and explains why they were flying blind:

From a SQL perspective… Some databases may have been completely unavailable, some would have experienced intermittent connectivity issues, and some databases would have been fully available. This uneven impact profile for databases in the degraded ring, meant that it was difficult to summarize which customers were still impacted, which continued to present a challenge throughout the incident.

Boy, I have been there. When multiple databases and servers go down, one of the first thing management wants to know is, “Which specific apps are down?” When you can’t answer that question, it makes management pretty nervous, and adds even more stress to the situation.

As we attempted to migrate databases out of the degraded ring, SQL did not have well tested tools on hand that were built to move databases when the source ring was in degraded health scenario. Soon this became our largest impediment to mitigating impact.

It might be tempting to point and say, “Well, Microsoft, you should have that” – and they should – but I don’t see a lot of shops with well-tested automated DR failover tools.

I’ve long said that Azure SQL DB does a better job of database administration than not having a DBA altogether, and this is a good example. Customers who didn’t have a DBA wouldn’t have been any better off managing their own DR in a situation like this, and frankly, most customers who do have a DBA wouldn’t have been better off either. (If you smugly think you’d be fine, point to your current list of production servers & databases, and prove that every single database you have is also synced with DR. Go ahead. I’ll wait.)

Because every DB moved required manual mitigation via scripts, it seriously undermined our ability to move fast even once impacted DBs were identified, and DB moves were scheduled.

Elsewhere in the post, they mention that over 250,000 databases were involved in just one of these troubled rings of databases alone. You just can’t manually do anything with 250,000 databases, so I can only imagine how stressful it was to try to write the automation code under fire. Props to the folks working that night.

Overall, this kind of incident – and how Microsoft responded to it afterwards – is why I think that if you don’t have a DBA, you could do a lot worse than relying on Microsoft, Amazon, and Google doing that job for you instead. Platform-as-a-Service lets someone else stress out about the outage, troubleshoot it as quickly as they can, then build better processes to shorten the next outage.

View Details

After consuming waaaay too much coffee, I went through your top-voted questions from https://pollgab.com/room/brento:

Here’s what we covered:

  • 00:00 Start
  • 03:53 It’s ‘a me: Is there a feature in SQL that Microsoft abandoned that you wish they had perfected?
  • 05:43 TheEveryDayDBA: My friend asks, he is using sp_blitzIndex on a OLAP db workload. Quite a lot of Indexaphobia: High Value Missing Index are trigger for a table, that contains a Clustered ColumnStore index on it. Does sp_blitzIndex look for ColomStore indexes when it runs?
  • 07:01 RenegadeLarsen: Hi Brent Any plans on going to SQLBits next year? Kind Regards RenegadeLarsen
  • 08:06 BrentIsMyHero: Hi Brent! You are my hero! 🙂 Can you please recommend your top 3 books for a Production DBA role. Thanks and have a great day!
  • 09:28 ascme: I’ve been a mssql DBA for 15+ years and have dabbled in other platforms. My company is moving most DB services to IBM LUW and MariaDB. I am half interested in learning more about them, but not sure that is a career building positive for me. What would you do?
  • 10:30 Ozan: Hi Brent, you recommend performing snapshot backups if the database size is greater than 1 TB. Why not also for databases with smaller sizes?
  • 11:18 Miles: Hi Brent,How do you handle egoistic managers or toxic peers who take credit for your work, don’t appreciate it, and hinder your promotion despite hard work? Have you faced such situations? Can you share your experiences and advice on dealing with them?
  • 13:16 unspoiled: I had an issue with excessive blockings, I tracked this down to be related to compile locks of which I have never heard of before. how do compile locks cause a wide spread blocking issues and how could it be prevented?
  • 15:41 Blue K: Is Azure SQL any better/worse for implementing one DB per customer than traditional SQL VM?
  • 16:59 Kaysar R: You mentioned using snapshot backup over native SQL backup for large terabyte DB’s. Do you recommend first upgrading to SQL 2022 before attempting snapshot backups?
  • 17:41 Chips Ahoy!: In a recent office hours you recommended that XML and JSON should be stored in the DB as a blob. You are also known to say “don’t put data in the DB unless there will be joins or filters on it” Seems contradictory. Did I misunderstand something?
  • 18:31 Red U: Have you seen anyone successfully automate the scale up / scale down process for Azure SQL VM? What were the lessons learned?
  • 21:04 Izzy G: What are the top issues your clients run into when querying SQL Server over a WAN instead of a LAN?
  • 21:32 It’s ‘a me: Hi Brent. You talk about backups a lot, but I’ve never heard you mention backing up to URL? Is there a reason you don’t mention it as an option? Drawbacks, reliability etc
  • 23:15 Faroek: Is the query store purely a logging feature, or does SQL Server also use it to re-use plans or check for plans to help with query executions?
  • 24:06 Grubsnik: In a recent office hours, you mentioned that SQL server has become much better a prioritizing ram over disk for tempdb in the last 5-10 years. Can you tell which version specifically? We’ve been running TempDB on ramdrives and I’m wondering if that is an antipattern for SQL2016
  • 24:56 Doug E: What are your thoughts on Microsoft purchasing Activision? Does this permanently hurt the competition?
  • 25:47 sandimschuh: What is a good way to identify queries that pose the risk of a sudden change in execution plan (switch from NL to a scan or visa verse)? The problem occurs with queries that use at least one index with heterogeneously distributed data (bad estimates) and nested subqueries.
  • 27:38 Lance Boil: What is your favorite cruise ship line and destination?

View Details

Today’s webcast featured an awful lot of questions from one particular person who was super-active at https://pollgab.com/room/brento: Here’s what we covered: 00:00 Start 00:03 Miles: Hi Brent, I am aware of “sp_statement” completed and sp_batch_completed events in trace and extended events. But, what is the use of rpc_completed event? How this event will be helpful...

View Details

You’ve been getting more and more deadlock errors, and users are starting to complain. You’re wondering if your queries are the root cause, and if so, what you should do to fix ’em. In a fast-paced session, I’ll explain the 3 causes for deadlocks, and the 3 ways to get relief. We’ll use 2 demo...

View Details

Today, I need your help with some of the top-voted questions from https://pollgab.com/room/brento. Chime in in the comments: 00:00 Start 00:52 Accidental DBA: Hello Brent. Thank you for keeping your Q& A sessions entertains and informative. My question is non-technical…Have you ever said this to your client? You keep using that word. I don’t think...

View Details

Today’s batch of questions from https://pollgab.com/room/brento requires some really long answers, and some are right to the point. 00:00 Start 02:13 Eh? Aye…: As DBAs, how can we best prepare for the AI world in terms of data? Should we start with AI as a concept fundamentals, or what ua the ‘data type’ we should...

View Details

Turns out y’all actually work over the summer – there are actually cool new features this month! I think I’m actually going to have to record updated sp_BlitzIndex, sp_BlitzLock, and sp_BlitzQueryStore modules for my “How I Use the First Responder Kit” class because these features are pretty awesome. To get the new version: Download the...

View Details

We headed up to the mountains to get away from the Vegas heat. Before the sun rose, I took your top-voted questions from https://pollgab.com/room/brento.   Here’s what we covered: 00:00 Start 00:36 Ozan: Hi Brent, how should Volume Snapshot Backups (VSS) be configured correctly that it will not freeze the database’s IO for a couple...

View Details

I took a break from packing my bags long enough to answer your top-voted questions from https://pollgab.com/room/brento. Here’s what we covered: 00:00 Start 02:42 T-man: Hi BO. A friend has multiple Distributed AGs (on separate business division servers) but needs to share ODS data with each of the DAG DBs. Any near-real time architecture ideas...

View Details

This year’s PASS Data Community Summit is November 13-17 in Seattle. (No online version is available this year – you gotta be there in person.) If you’ve attended in person before, you already know the value: it’s like a family reunion for the Microsoft data community. It’s your chance to see the authors you’ve read...

View Details

I went through the top-voted questions from https://pollgab.com/room/brento and discussed ’em live on my Twitch channel.   Here’s what we covered: 00:00 Start 00:39 tanchenglai: Hi Brent! We bought your Level 2 Bundle last year. Recently, we went into frequent thread pool issues; we suspect it is due to high CPU utilization. Our IT manager...

View Details

Y’all posted so many good questions at https://pollgab.com/room/brento that I went longer than usual this time: Here’s what we covered in this episode: 00:00 Start 02:17 Tanchenglai: Hi Brent, recently we always ran into thread pool issue. I checked Performance Dashboard and found that CPU spiked over 80% occasionally. I suspect apps can’t connect after...

View Details

While on a road trip, Richie stopped by a used bookstore (or would that be used book store?) and made an amusing observation about the relative value of different SQL Server books. I just had to go look at Amazon for some research. I’m listing prices below, but keep in mind that when you click,...

View Details

I step away from the backyard long enough to take y’all’s questions from https://pollgab.com/room/brento. Here’s what we covered in this episode: 00:00 Start 02:23 Stockburn: Hi Brent, we are using distributed always on AGs, with a node in AWS for DR. We are thinking of using this to quickly migrate the work load to the...

View Details

There are only a couple weeks left in this summer’s marathon of Office Hours sessions, which means there’s limited time left to ask your toughest database problems (not trivia questions) at https://pollgab.com/room/brento. Here’s what we covered in this episode: 00:00 Start 03:22 tanchenglai: Hi Brent, I have implemented a system that records data in another...

View Details

Is your company hiring for a database position as of August 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment. The rules: Your comment must include the job title, and either a link to the...

View Details

I took your questions from https://pollgab.com/room/brento before heading out to pick up my Cadillac from the mechanic. Here’s what we covered: 00:00 Start 04:50 JudgeDredd: Hi Brent, have you ever been asked for opinion/expertise (as a database specialist) in a court trial? If yes, could you share some details? 07:10 Aart Bluestoke: A maximum of...

View Details

Post your SQL Server and Azure SQL DB questions at https://pollgab.com/room/brento and upvote the ones you’d like to hear me discuss. Here’s what we discussed in this episode: 00:00 Start 02:47 therealprodDBA: In the last webcast, I heard you cite that majority of your clients are on AWS. I got curious now that my shop...

View Details

To celebrate this month’s launch of our new class, Fundamentals of Azure Networking for the Data Professional, we’re making one video a day completely free. Here’s what’s on tap this week: July 24: Demo: Working With a VPN July 25: Hub and Spoke vs Mesh Design Patterns July 26: Microsoft-Managed Virtual Networks July 27: Demo:...

View Details

Seriously, how do y’all keep coming up with so many great questions? I went through your top-voted questions from https://pollgab.com/room/brento/ on a live stream on my Twitch channel, like I do on most Wednesdays & Thursdays, and really enjoyed these: Here’s what we covered: 00:00 Start 04:14 Groove_timer: Hey Brent, Trying to convince my employer...

View Details

Stack Overflow was down, so y’all posted questions at https://pollgab.com/room/brento and I gave ’em my best shot. Here’s what we covered: 00:00 Start 04:33 Amir: Does Az-900 worth the effort and money? What about other microsoft certifications? 06:16 Mr. M: Hi Brent. Which feature in SQL Server you like the most? 08:43 Q-Ent: Hi Brent,I...

View Details

The short story for this quarter: SQL Server 2022 adoption rates have stalled, even backtracked, and it doesn’t appear to be due to the cloud, either. For the long story: ever wonder how fast people are adopting new versions of SQL Server, or what’s “normal” out there for SQL Server adoption rates? Let’s find out...

View Details

To celebrate this month’s launch of our new class, Fundamentals of Azure Networking for the Data Professional, we’re making one video a day completely free. Here’s what’s on tap this week: July 17: Demo: Using Virtual Networks for Data Services July 18: Demo: Private Networks Without Public Access July 19: Demo: Multiple Private Networks July...

View Details

Almost all of today’s questions from https://pollgab.com/room/brento were great! Well, except two. Here’s what we covered: 00:00 Start 02:13 Andrei: What’s the appropriate response/punishment for developers who insist on storing json and xml in nvarchar(max) fields? 03:43 JustGoogleIt: What are your thoughts on Jeff Moden’s “Black Arts” Index Maintenance — GUIDs v.s. Fragmentation? How would...

View Details

Raise your hand if you’ve ever blamed the network. You’re responsible for the health, security, and uptime of your company’s data services in Azure. You’ve provisioned a few services, but every now and then, you run into problems making your services reachable and reliable from different users and app servers. You want to understand: Your...

View Details

The first time I saw FOR XML PATH being used to generate a comma-delimited list, I think I stared at it, shook my head to clear the cobwebs, stared at it some more, and then closed the code editor thinking it was complete witchcraft. And that same thing probably happened the next several times, too....

View Details

Y’all posted & upvoted questions at https://pollgab.com/room/brento, and we finished up the session talking about the relationships between developers and database administrators. Here’s what we covered: 00:00 Start 02:35 Nortzi: Hi Brent. Is there a way to optimize sorting a result using a column from a different table? Using POC index pattern (partition,order,covering) works great...

View Details

At https://pollgab.com/room/brento, post the questions you’d like to get my opinion on, and I’ll take a break every now and then at the office and go through ’em. Here’s what we covered in this episode: 00:00 Start 01:08 #ARRRRRGH: Hi Brent. Have you seen anybody put good visualisations on top of sp_Blitz? Im trying to...

View Details

Today’s live stream was a little different: I demonstrated using the Aiomatic WordPress plugin, ChatGPT, and Azure Open AI to write blog posts. I showed the kinds of content it writes, the kinds of blog post content it doesn’t include, and taught you how to identify meaningless word salad blog posts written by people who...

View Details

I can finally see the finish line in my backyard renovation, now that the concrete’s going in. I took a break from watching the construction folks to go through your highly upvoted questions at https://pollgab.com/room/brento: Here’s what we covered: 00:00 Start 02:03 Fabricator: Hi Brent, what is your take on the recent lunch of Microsoft...

View Details

You’ve got an existing application with a database back end. You’re thinking about changing the database, and you don’t wanna break stuff. The most important thing to understand is difference between constructive and destructive changes, also known as additive and destructive changes, or non-breaking and breaking changes. Constructive change examples: adding a new table or...

View Details

Sometimes, I don’t care if questions get a lot of upvotes at https://pollgab.com/room/brento – I just don’t wanna answer ’em. They’re not necessarily bad questions, but I’m just not interested in them, or I’ve answered them repeatedly, or I don’t have a good answer. Maybe y’all do, though, so I’ve numbered these. If you want...

View Details

I start today’s Office Hours by playing with the very underwhelming Github Copilot in ADS, then take your questions from https://pollgab.com/room/brento. Here’s what we covered: 00:00 Start 04:06 Github Copilot in Azure Data Studio 24:36 Byron: Seeing plan cache queries for a long since retired table. What is best way to track down the app...

View Details

This one’s a pretty quiet release: just bug fixes in sp_Blitz, sp_BlitzLock, and sp_DatabaseRestore. To get the new version: Download the updated FirstResponderKit.zip Azure Data Studio users with the First Responder Kit extension: ctrl/command+shift+p, First Responder Kit: Import. PowerShell users: run Install-DbaFirstResponderKit from dbatools Get The Consultant Toolkit to quickly export the First Responder Kit...

View Details

I have been absurdly lucky to be around so many amazing and inspirational managers. Almost everything I know was taught to me by someone else. Over my life, I’ve learned so much about careers, marketing, business, communications, teaching, databases, you name it. For this month’s T-SQL Tuesday, Gethyn Ellis asked us to share the best...

View Details

One of the things I love about SQL ConstantCare® (which happens to be free this month, by the way) is that I can keep in touch with what y’all are actually doing on your production servers. Today’s lesson was a complete shocker to me: some of y’all are changing the compatibility level on the master...

View Details

It’s back to lighter fog-friendly clothes as the ship pulls into San Francisco and I answer your questions from https://pollgab.com/room/brento. Here’s what we discussed: 00:00 Start 01:16 Pozzolan: Hey Brent, My companies budget for SQL licensing is small. In such situations, does it make sense to switch or start all new development on something like...

View Details

One of the big principles of our SQL ConstantCare® monitoring product – which happens to be free this month – is that we only wanna tell you things you’re actually gonna take action on. Anytime we email you advice, there a few “Mute” links that you can click on to never hear this advice. You...

View Details

Last week, I asked if y’all had been to in-person regional events before, and whether you were going back. I wanted to know because Data Saturdays and SQL Saturdays are starting to happen again, but … attendance seems way down from pre-COVID numbers. I wondered, are people just not going to return to conferences for...

View Details

I stopped piloting the ship long enough to answer your top-voted database questions from https://pollgab.com/room/brento. Here’s what we covered: 00:00 Start 00:42 Dirty_Pages: You mentioned recently how much you swear, what is your favorite swear word(s) and why? Any favorite insults? 02:38 SQLCircus.Clown: What is your go to/default SQL datatype for storing a run of...

View Details

Thankfully, we didn’t hit any icebergs or glacier droppings, so I put my comfiest coat on to answer your top-voted questions from https://pollgab.com/room/brento. Here’s what we discussed: 00:00 Start 01:29 gb DBA: Hi Brent, I have over 200 threads with BROKER_RECEIVE_WAITFOR type when I execute sp_whoisactive and some of trx have high numbers on reads...

View Details

In May, Amazon brought out a new Aurora I/O Optimized Serverless instance type. By switching to it, we cut our database costs by 43% overnight, saving us about $1,200 per month.

No strings attached. Just lower prices.

So what’s the magic? Well, customers of our SQL ConstantCare® service send us diagnostic data every day for thousands of SQL Servers around the world. We import that data, process it, analyze it, and then send emails with specific actions we want the customers to take on their servers.

It’s a lot of data shuffling around, which means a lot of IO. We bring in so much new data every day, and we only keep 30 days of it online. We can’t just tune queries to cut IO: it’s legitimately new data going into the system, and that’s gotta make it to disk. (We’ve even tried cutting the data we import, too.)

When we broke out costs per day, the top cost was IO:

That’s the magic of AWS’s newest serverless price offering: it’s specifically designed for people who do a lot of IO. Amazon’s press release said it would offer “up to 40% cost savings for I/O intensive applications where I/O charges exceed 25% of the total Aurora database spend.” That’s us, alright!

If you’re using AWS Aurora, and your StorageIOUsage costs are like ours, you owe it to yourself to flip the switch over to the new instance type. Go into the portal, modify your cluster, and check out the storage configuration options:

You can switch over to I/O optimized with just mouse clicks, no cluster changes or app changes required. If you find out the cost structure doesn’t work out in your favor, you can just switch right back. (AWS does have guardrails in place to make sure you don’t flip back & forth repeatedly for busy periods.)

This new change helped us confidently run free trials for SQL ConstantCare® this month, too. Why not try it and see what you learn about your SQL Servers?

View Details

Two short yes/no questions about regional & national conferences:

I've been to an in-person event like SQL Saturday, PASS, SQL Bits before:(Required)YesNoEvents likeI intend to go to an in-person event again in the next 12 months:(Required)YesNo Δ

(If you can’t see the yes/no questions or the results, click here to view the blog post.)

I’ll close the poll after a week and write up my thoughts about the results.

View Details

You’re responsible for the health and performance of your company’s SQL Servers.

You can’t afford most monitoring products because they’re priced per-server. Your manager just can’t justify spending tens of thousands of dollars.

Besides, monitoring tools just spam you. You end up with an Outlook rule that dumps all their emails into a folder, and what’s the point of having a monitoring system at that point?

Meet SQL ConstantCare®. For one low price, we send you just one email per server per day, only when there are specific tasks you need to perform on that server.

Over 300 companies rely on it every day to monitor over 2,000 SQL Servers.

This month, we’re offering a free 30-day trial: sign up for either the $895/year plan or the $95/month plan, and we won’t charge your card for 30 days. Don’t like it? Don’t feel like you learned enough about your servers? Just cancel anytime before 30 days is up, and you won’t pay a thing.

Wanna learn more? Check out the quick start instructions and the frequently asked questions.

Let’s see what you learn about your SQL Servers!

View Details

En route from San Francisco to Juneau aboard the Ruby Princess, I stopped to hit a few of your questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:46 DBACAT: Hi Brent, what statistics impact occurs when a transaction is rolled back? The query’s exec plan didn’t change but duration and CPU jumped 10X. Stats were updated at the time of the transaction. Does SQL roll stats back? It doesn’t seem so. Seems like SQL got all confused.
  • 04:33 Whiny App Developer: Hi Brent a well-intentioned index has been added to our app’s database. My friend can see it has caused one query to slow down, and the team aren’t sure when it was added or what it might have sped up. What’s your opinion on DBAs making changes without informing the app’s team?
  • 06:11 RaduDBA: I don’t necessarily have a question, but I need some encouragement and emotional support since my company still uses SQL 2000 (not a joke, not a type) and they don’t want to migrate since the app still works fine. It’s a government institution, somewhere in the Midwest.
  • 07:17 Whiny DBA: Hi Brent, what is your opinion of developers that want total control of non-clustered index creation/modification/deletion on production SQL servers?
  • 08:45 Eduardo: Do you recommend any specific MS Excel skills for the production SQL DBAs?
  • 08:54 Mars: Hi Brent, what are your predictions for DBA in a next 10 years? And how do you feel about the chatgpt etc. Is it a threath for DBAs? And if yes what we should do to save our jobs? Bit shout Out to you and what are you doing for sql community. Thanks
  • 11:07 Arlo Fuller: Hi Brent, what realistic options are available for implementing multi-master replication between multiple Always On Availability Groups? I had looked at peer to peer replication but not sure if it supports AAG’s.
  • 12:44 Ildjarn: Have you ever considered using Powershell for sp_Blitz, only querying the data that you need with e.g. dbatools, and then do the parsing in Powershell? The advantage would be that you offload the parse stuff to a management system, leaving CPU free for SQL Server’s actual job

View Details

I’m still blown away that I have a blog post here that says, “Last updated: 21 years ago.”

It’s pretty fun to see old pictures of me in the media library, too.

When I first started blogging over two decades ago, it wasn’t a business. I just did it because I enjoyed writing, sharing, and being part of an online community. It was a fun outlet, a way to contribute something in my spare time, and a method to record my life in a way that might enable me to look back later and see what I’d been doing years ago.

For 2 more days, to celebrate the 21st anniversary, I’m running a sale, too:

Fundamentals$312per year* Fundamentals Classes * Save $83

Sign upMastering$786per year* Mastering Classes * Save $209

Sign upFundamentals + Mastering$944per year* Fundamentals Classes * Mastering Classes * Save $251

Sign up

View Details

Okay, so, the last few Cumulative Updates have had known issues around broken remote queries using the generic ODBC connector and errors with contained availability groups, but I couldn’t really care less about those. If you use those features, I give you bombastic side eye anyway.

However, in the last few days, two more known issues have surfaced.

The first problem is that Cumulative Update 4 can give you incorrect query results when all of these are true:

  • Your index explicitly specifies the sort order, like DESC ~~or ASC~~ (see update below)
  • Your query has a WHERE filter on that sorted column using an IN list or multiple equality searches
  • Your query has an ORDER BY with the sort order as the index (which is, after all, why you created the index)

So for example, this can give me incorrect query results:

CREATE INDEX DisplayName ON dbo.Users(DisplayName DESC);SELECT * FROM dbo.UsersWHERE DisplayName IN (N'Brent Ozar', N'Jon Skeet')ORDER BY DisplayName DESC; To work around that problem, the CU4 documentation suggests you uninstall CU4 or enable trace flag 13166 and free the plan cache.

Update: in the comments, Paul White points out that trace flag 13166 skips a logic step when building query plans, but it only applies to descending index keys. That means the CU4 documentation might be wrong, and this bug might only apply to indexes with a descending key specified.

The second problem is memory dumps every 15 minutes if you have both Query Store and Parameter-Sensitive Plan Optimization (PSPO) turned on. Microsoft says they’re working on this issue, but for now, the workaround is to disable Query Store or PSPO, or continuously delete PSPO plans from Query Store yourself.

Should you do new installations of SQL Server 2022 today? I’m not going to give you the answer, dear reader – instead, I wanna hear your opinion in the comments. If you were deploying a mission-critical production server in June, which SQL Server version would you pick?

View Details

Is your company hiring for a database position as of May/June 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Goooood morning, party people! Today is the opening day of the annual Microsoft Build conference, an event focused on people like developers and power users who build things with Microsoft tools.

I’ve never attended Build in person before because the data part of the event tends to be fairly thin, and the releases for Azure SQL DB and SQL Server aren’t usually tied to Build’s dates. This year, it’s a hybrid event, both in-person in Seattle and online.

I’m at home in Vegas, attending virtually, and I’ll live-blog the keynote. Refresh this page starting at 9AM Pacific, noon Eastern, to see my thoughts on news as it comes out.

The first bits of news are already starting to trickle out: this morning, the SSMS release notes were updated to mention Microsoft Fabric SQL Endpoint and Fabric Data Warehouse. Yes, those would be new products, and yes, Microsoft already has something called Fabric, but this is different. If you’re bored before the keynote, you can go through this morning’s Github checkin for the Build event.

You can join me, but to do it, you’ll need a free registration for Build, so head over there now before the keynote starts at 9AM Pacific.


8:45AM: Based on this morning’s check-ins, looks like they’ll be announcing Hyperscale databases in elastic pools. Each Hyperscale elastic pool supports up to 25 databases on standard series hardware, max 100TB data in the pool. Still stuck at 100 MB/sec throughput on the log file though, and even worse, it maxes out at 130MB/sec across the entire pool.

8:49AM: From the new documentation: Fabric Data Warehouse “provides two distinct data warehousing experiences. Each Lakehouse automatically includes a SQL Endpoint to enable data engineers to access a relational layer on top of physical data in the Lakehouse, thanks to automatic schema discovery. A Synapse Data Warehouse or Fabric Warehouse provides a ‘traditional’ data warehouse and supports the full transactional T-SQL capabilities you would expect from an enterprise data warehouse. Either data warehousing experience exposes data to analysis and reporting tools using T-SQL/TDS end-point.”

8:54AM: From the documentation update list: “Optimized locking available in Hyperscale – Optimized locking is a new Database Engine capability that offers an improved locking mechanism that reduces lock memory consumption and blocking amongst concurrent transactions. This fundamentally improves concurrency and lowers lock memory. Optimized locking is now available in all DTU and vCore service tiers, including provisioned and serverless.”

8:58AM: Analysis thoughts on reading the Github checkins so far: this looks like yet another iteration of Microsoft’s data warehousing strategy that just can’t maintain focus for 3 years straight. From DATAllegro to Parallel Data Warehouse to Hadoop to Analytics Platform System to Azure SQL Data Warehouse to Azure Synapse Analytics to Big Data Clusters, there’s something broken about the leadership vision here. I feel sorry for folks who have to sell Microsoft data warehousing with a straight face: before the deployment finishes, the product’s already been “reinvented” again.

At the same time, I’m also so happy to be working in the relational database space. The language is stable, the product is stable, and I don’t have to tell clients to keep changing the way they access the database. Thank goodness for that.

9:05AM: Hmm, I thought the keynote started at 9, but they’re still running promo videos. Hmm.

9:09AM: Okay, I think this is actually supposed to be the keynote – they’re showing videos of people interacting with AI.

9:10AM: Satya Nadella took the stage and talked about his first Microsoft developer conference. He flashed back through big moments in computer history like The Mother of All Demos, the PC, client/server computing, etc. “All of this has been one continuous journey.” And a hell of a ride it’s been so far.

9:13AM: Satya called ChatGPT’s launch the Mosaic moment of this generation. I think that’s fair, but I had to chuckle – few people remember Mosaic. It was an early thing that’s long since been discarded by the wayside. If that happens to OpenAI, Microsoft is gonna be pissed about their multi-billion investment.

9:15AM: “We’re gonna have 50+ announcements, but I want to highlight 5 of them.”

  1. Bringing Bing to ChatGPT. (No claps.) Satya: “You can clap.” (Claps, awkward)
  2. Windows Copilot. I don’t think Cortana ever did that well on Windows desktops – at least, I never see anybody using it – so it makes sense to throw something else at it instead. For corporate PCs with security lockdown, this gives Microsoft another O365 revenue stream, because I’m sure they’ll offer a “secure” Copilot that doesn’t use your documents for training.
  3. Copilot stack. So other folks can build Copilot for their own infrastructure using Microsoft’s models and AI infrastructure. Totally makes sense given Microsoft’s developer focus – if they can make this easy in Visual Studio, then it stands a chance. I was just horrified by the demo, though: using Copilot in Office, taking legal advice from ChatGPT in Word. I can’t imagine how that might backfire. (Who the hell thought this was a good idea for a demo?!?)
  4. Azure AI Safety. Testing, provenance, and deployment.
  5. Microsoft Fabric. “The biggest data product announcement since SQL Server.” Unified storage and compute, unified experience, unified governance, and unified business model.

9:32AM: Microsoft Fabric looks like a data lake where you have a team who governs what goes in & out, regulates the schema and security, tracks the data lineage, and curates the data model. So, uh, a data warehouse?

9:35AM: Satya’s doing human storytelling, so I’ll focus on Fabric for a second here. Fabric is a story about what happens when your data is well-controlled. That was the story of the data warehouse 20 years ago: it solved exactly the same pain points. Data warehouses fell out of favor because there was too much data, changing too quickly, and the tools changed too quickly.

Data lakes became popular because people wanted to just dump the data somewhere and figure things out later. Over time, that ran into the same problems that we used to have before data warehouses: the data wasn’t reliable, we didn’t know where it came from, the changes kept breaking reports, etc. So now, Microsoft Fabric is fixing the same problem with data lakes that data warehouses fixed with scattered relational databases.

Will it catch on? Maybe – data warehouses did – but you can fast forward and see what’s going to happen when Fabric is popular. Users will say, “I have this extra data that I need to join to my reports right now, and I don’t have the time to wait for the Microsoft Fabric admins to bring it in, so I’m just going to put it in this one place for now…”

And we’re right back where we started. Okay. If your company couldn’t fix the data warehouse’s problem, and they added data lakes, and they couldn’t fix those problems, so now they’re implementing Microsoft Fabric… I’m just gonna say maybe the problem isn’t the product you’re using.

Does that mean Fabric is a bad product? Not at all – it might be great – but it’s definitely not something I’m going to pursue.

9:40AM: Kevin Scott, CTO & EVP of AI at Microsoft, took the stage to talk about the era of the AI copilot for the next half-hour. That’s a great topic, but it’s not really my jam, so I’m going to stop the live blog here. Right now, Build’s session catalog doesn’t have any Fabric sessions, but I wouldn’t be surprised if sessions got added over the next hour or two. I’m not going to dig more deeply into there either.

Update: Optimistic Afternoon ThoughtsWhen I walked away from the computer and emptied the dishwasher (true story), I realized I wasn’t being completely fair to Fabric. There are companies who:

  1. Successfully implemented a secure, well-documented, rigid data warehouse, and
  2. Who also implemented Azure Data Lakes later, and
  3. Now want to control those lakes the same way they control their data warehouse

And for companies like that, Fabric makes a lot of sense. I don’t have a sense for how big or small that market is today, but I’m sure it’s out there – it’s the kind of thing Microsoft BI consultants would facilitate.

I think this also plays to Microsoft’s strengths: they control the cloud, the most common relational databases, the reporting tools, and the development tools. You could make an argument that Fabric stitches those pieces together in a way that Amazon and Google won’t be able to do for years, if ever. (Sure, AWS has Redshift, but that’s just a persistence layer – Microsoft is trying to argue that Fabric is a cohesive unit that brings it all together.)

Paul Turley’s a BI pro who specializes in the kind of market that Fabric services, and he has a quick summary here, plus a list of learning resources. Note the number of different tools involved in his posts and the links – Fabric isn’t just “one thing”, it’s a brand name for a whole bunch of moving parts that have been flying under different brand names over the last few years. Fabric feels like the latest brand name and vision – and that’s where I get nervous, seeing how Microsoft keeps reassembling these parts into different things.

View Details

Y’all post questions at https://pollgab.com/room/brento, and I go through the top-voted ones on my Twitch channel streams.

Here’s what we covered today:

  • 00:00 Start
  • 01:56 Manoj: Where do you see artificial intelligence having the most impact on DBA’s?
  • 03:25 It’s ‘a me: Hi Brent, is it still “best practice” to have databases split into multiple mdf files in the days of SSDs? Especially since the files live on the same SSD
  • 04:57 Mr. SqlSeeks: Is it an accurate assumption that as SQL Server cardinality estimates improve, the query engine gets more aggressive in using those estimates to build plans, which is why some queries are awful once you change the compat level? Were the previous engine versions more forgiving?
  • 08:03 StillLearning: Hi Brent, I’m trying to understand why so many people think that using partitions with SQL Server will improve the performance of their queries. I don’t know much about Oracle, but It seems that Oracle partitions can improve some queries. Could this belief come from there?
  • 09:50 Eduardo: Should you purchase third party monitoring software for Azure SQL DB?
  • 12:24 Malmo: What’s your opinion of simultaneously using both bitlocker and SQL TDE to protect SQL data?
  • 13:23 marcus-the-german: Hi Brent, let’s say I have a AG, which is setup correctly to read the data from the secondary (the routing is correct, not the network routing ;-)), the app is configured to read from the secondary. If so, should I see the select statements in the secondary’s activity monitor?
  • 14:41 Stimpy: What are the top challenges that versionless SQL server poses to the first responder kit?
  • 16:48 Janus: See lots of videos for SQL on linux but does this feature really get used all that much?
  • 17:26 Leif: On a really wide table where users search on every column, will it be best to use column store index? Or will tables with a lot of rows gain the most from CS index?
  • 19:52 Going_Parallel: Brent, How do you best prevent yourself from “burning out”, and recognizing when you need to take a step back? Relevant for all job, but certainly in our field.
  • 23:25 Nortzi: Hi Brent. I’ve heard from you and from others that it’s a really bad idea to shrink your data files. Other than causing index fragmentation are there other compelling reasons not to do this?
  • 24:30 David Singleton: Hi Brent, thanks for sharing, your recorded classes are a bargain and have saved my butt many times now. Is there some way in an SSMS query to tell it which SQL server to connect to? Something like the SERVER equivalent of how USE works to tell it which DATABASE to use.
  • 28:07 m2devdotnet: Random, non-SQL related question – do you have any pictures of your office layout? We’re moving into our new house and I like your setup and curious what the overall layout is
  • 30:53 Y?mò: How should DBAs describe what they do for a living to non technical peeps?

View Details

You post questions at https://pollgab.com/room/brento and upvote the ones you’d like to see, and my job is to come up with accurate answers on the fly. Let’s see how I did.

Here’s what we discussed:

  • 00:00 Start
  • 03:25 SickOf: Brent is there a backup product you can recommend?
  • 04:38 OneEyebrowRaised: I’m noticing three significant shortfalls in Always On: 1) Login synchronization is manual, 2) Scheduled Jobs synchronization is all manual, 3) stored procedures put in the system databases aren’t shared across nodes. Do you know of any tools to address these shortcomings?
  • 06:11 Sean C: Hi Brent, TIA for roasting me lol. We use dynamic SQL to loop through 200+ cols to validate against a set of specs, resulting in a lot of plans being painted when tuning. Is there a way to suppress benign exec plans like looping through commands, etc to reduce bloat?
  • 07:47 I’ll be BacH: Is Data Modeler still a career path? Or has that merged into Database Developer? Do you see any sub-specialties in the Database Developer career field?
  • 10:05 Doug: Do folks ask easily Googled questions intentionally?
  • 11:11 Isaac Wahnon: You answered Rojo about using Distributed AGs for version upgrades, saying “No because it’s so much work to set up.”We want to upgrade from 2019 to 22,What upgrade procedure can reduce risk and downtime for a system with AGs and Distributed AGs? In-place or replace.
  • 12:27 macfergusson: Hey Brent, in one of your courses you mention using GUID PKs and clustered indexes, they aren’t nearly the bad choice that a lot of DBAs make it out to be. If you do go this route, are there any different best practices that you recommend? Fillfactor, extra memory?
  • 13:11 JediMindGorilla: Hi Brent. I always tell people “I am not the guy that can code a cup of coffee from 0, I am the guy that makes it taste better”… is it common to have people looking for SQL jobs that may not have as much “coding” experience (code from scratch), but are good at performance?
  • 15:15 Sammy: An architect I know likes to default every Primary Key INT with -2,147,483,648 or BIGINT and its lowest to avoid resizing. Brilliant or needlessly clever?
  • 15:57 Accidental_dba: Can we run multiple backups on a single server as we have 100+ databases? Currently we use olaha scripts. Currently backups starts at 12am and finishes around 7am which is when all our stores open? Trying to make backups finishes by 5am
  • 18:18 Just_Winging_It: Brent, In your experience, when you rebuild indexes and fragmentation is still present, what are the usual suspects to check? Please feel free to roast me.
  • 19:14 gjocarroll (George): Hi Brent, have you encountered any new entry into your Top 5 Waitstats/issues in the last few years/SQL Server versions?
  • 20:35 Universe For Rent: I’m often tasked to review SQL code that’s about to be pushed to production.
  • 22:04 ArchibeaR: Been working with SQL Server since 6.5…. I know i’m old. Working with a new team building Azure setup from the beginning. Wondering if you have some suggestions on reading to get upto speed.
  • 22:46 Developer Who Cosplays As a DBA: I recently ran into compilation timeouts in a prod database that caused web pages to time out, and I’d love to put together a demo of comp. timeouts for educational purposes. Do you have any tips for how you would go about intentionally writing a query with a long compile time?
  • 23:45 Ive_Got_Heaps: Hypothetical: Brent decides to sell all of his cars (see hypothetical) to fund a new database engine. What are your dream bells and whistles? Sub question, when can I invest?
  • 25:18 Piotr: What’s the largest server you have seen log shipped? Any issues with shipping large servers?
  • 27:15 core: hey Brent! Is there any easy way to detect SQL Server Agent missed jobs? For example, if the SQL Server Agent is stopped due to an issue with the service, server, or planned maintenance. thanks!
  • 27:14 Guilty DBA: Hi Brent, is there any way to configure the querystore (QS) to handle identical Pans more efficiently ?
  • 29:21 Yevgeny: How far back in SQL versions does office hours go back? Has the format / content / hairstyle of office hours changed much since then?
  • 30:54 Haydar: Is there a good way to programmatically obtain the query hash / query plan hash of a query after execution for auditing purposes?
  • 31:40 Eduardo: How do you recommend implementing sproc debug logging when the sproc could be running on AG primary or AG readonly secondary node?
  • 32:40 Wren: Hi Brent! Do you think the noted 2019 query/performance slowdown might patched any time “soon” (next year or so)? Or is it just too “baked in” to the version?
  • 34:25 Jessica: Hey Brent, I’m going to be in Vegas for a tech conference in about a month. What’s a good local restaurant or coffee shop that are just amazing to go to that are away from the “tourist” areas
  • 35:58 GP Geek: How do you get more than 8k or 4k into an NVARCHAR or VARCHAR variable? I’ve had a recent case where the limit was reached without the user noticing it and missing data

View Details

Step 1: go into Tools, Options and set this:

Step 2, set this:

Step 3, check this box:

And presto, no one will ever again question whether or not you know what you’re doing.

View Details

It’s pretty cool to look at a blog post and see, “Last updated: 21 years ago.”

It’s pretty fun to see old pictures of me in the media library, too.

When I first started blogging over two decades ago, it wasn’t a business. I just did it because I enjoyed writing, sharing, and being part of an online community. It was a fun outlet, a way to contribute something in my spare time, and a method to record my life in a way that might enable me to look back later and see what I’d been doing years ago.

For example, 20 years ago:

  • I built a computer for my car, and gazed wistfully at Ferraris
  • Bought pantyhose to build my own aquarium filters
  • Published articles in the biggest computer user group’s magazine
  • Wrote my own RSS feed

By 15 years ago, I had already started to focus mostly on SQL Server:

  • Explained Amazon Web Services offerings for a sample client
  • New StackOverflow database server coming, and log shipping it to Amazon S3
  • Talked about how fancy new SSDs were the “world’s fastest storage”
  • Still shared random pictures, like my dog wearing two coats

By 10 years ago, BrentOzar.com was a full-fledged business. The blog posts not only targeted tech exclusively, but the post titles were now aware of the importance of search engine optimization:

  • 7 Things Developers Should Know About SQL Server
  • SQL Server Table Partitioning Tutorial – including videos, because we’d learned the importance of video training
  • We launched our first in-person class in Atlanta
  • sp_Blitz was a popular thing, although at the time it was still copyrighted and closed-source
  • The company grew to the point where we held corporate retreats

By 5 years ago, we were deeply focused on technical SQL Server issues, but also covered technologies relevant to the DBA space:

  • We did industry salary surveys, and started asking tough questions about the data
  • We were working on getting sp_Blitz to work with the fancy new Managed Instances preview
  • We explained why DBAs might want to learn DevOps
  • We were building SQL ConstantCare® on AWS Lambda

Of course I have a straight face under here, why do you ask?Over the last few years, during the pandemic and up to today, I focused a lot of the blog content on live streams & recorded videos.

I wanted to give people a community where they could see a friendly face – even when the world wasn’t open for business, and faces were covered with masks. Database work is often lonely because so many of us are the only person in our company who does what we do, and the pandemic and remote work only made those things tougher. Many of the data professionals I know are struggling with burnout and loneliness.

Those of us who’ve been lucky enough to be around other people again, whether it’s work-related stuff or friends, have started to recover. Free regional in-person events like SQL Saturdays and Data Saturdays are starting to come back to life, and big ones like SQLBits and the PASS Summit offer hope that we’ll be able to do family reunions on a more regular basis again.

However, the data community is like a river: you can never step in the same river twice. Not only have the places and ways we meet up changed, but the members of the community have changed, too. Over a decade, many of us transition to different adjacent technologies, different lines of work, or switch to management.

I took December-February off to step back and think about what I personally wanted to do next, too. Was it time for me to transition? Had I done everything there was to do in Microsoft’s relational database engine, and was it time to move on? (I certainly don’t know everything in Microsoft’s data stack altogether – the product list is huge, as is the depth of each product.)

I came to the conclusion that it was time to go back to the start, and take a fresh look at Azure SQL DB and SQL Server. The products are still widely used, and every day, more people start using them for the first time. I’m not aiming to teach new things to folks who’ve read the blog for the last 20 years – but rather, teach things in fun, friendly new ways, helping people solve database problems faster.

Wanna learn from me? This month to celebrate the 21st anniversary, I’m running a sale, too:

Fundamentals$312per year* Fundamentals Classes * Save $83

Sign upMastering$786per year* Mastering Classes * Save $209

Sign upFundamentals + Mastering$944per year* Fundamentals Classes * Mastering Classes * Save $251

Sign up

View Details

This month’s big changes are performance tuning in sp_BlitzFirst & sp_BlitzLock.

Part of the benefits of using the open source FRK is that when any of us work with really big/fast/ugly servers, we tune the FRK procs to work better in those environments – which means it’ll likely work better in yours, too. For example, this month I was working with a server doing 30k-35k queries/sec and hitting threadpool issues, and I wanted sp_BlitzFirst to return more quickly in that kind of environment, so I tuned it.

Wanna watch me use it? Take the class.To get the new version:

  • Download the updated FirstResponderKit.zip
  • Azure Data Studio users with the First Responder Kit extension:
    ctrl/command+shift+p, First Responder Kit: Import.
  • PowerShell users: run Install-DbaFirstResponderKit from dbatools
  • Get The Consultant Toolkit to quickly export the First Responder Kit results into an easy-to-share spreadsheet

Consultant Toolkit ChangesI updated it to this month’s First Responder Kit, but no changes to querymanifest.json or the spreadsheet. If you’ve customized those, no changes are necessary this month: just copy your spreadsheet and querymanifest.json into the new release’s folder.

sp_Blitz Changes* Fix: exclude sp_PressureDetector from recompile checks. (#3244, thanks Edgar Walther.)

sp_BlitzFirst Changes* Enhancement: new @OutputResultSets parameter lets you return less result sets when you’re in a hurry. (#3255) * Enhancement: performance tuning for faster response time on systems with thousands of simultaneous active queries. (#3257) * Fix: no more arithmetic overflow on queries with horrific row estimates. (#3241, thanks SQLLambert.) * Fix: remove @@ROWCOUNT to avoid problems with In-Memory OLTP. (#3237) * Fix: only alert on bad cardinality estimations for queries that run > 5 seconds. (#3253)

sp_BlitzLock Changes* Enhancement: faster performance. (#3232, thanks Erik Darling.)

sp_BlitzWho Changes* Fix: no more date errors when a request’s start date is 1900. (#3243, thanks Jeff Mosu.)

sp_DatabaseRestore Changes* Enhancement: new @FileExtensionDiff parameter for folks who want to name their differential backup extensions different than Ola’s defaults. (#3234, thanks Will Spurgeon.)

For SupportWhen you have questions about how the tools work, talk with the community in the #FirstResponderKit Slack channel. Be patient: it’s staffed by volunteers with day jobs. If it’s your first time in the community Slack, get started here.

When you find a bug or want something changed, read the contributing.md file.

When you have a question about what the scripts found, first make sure you read the “More Details” URL for any warning you find. We put a lot of work into documentation, and we wouldn’t want someone to yell at you to go read the fine manual. After that, when you’ve still got questions about how something works in SQL Server, post a question at DBA.StackExchange.com and the community (that includes me!) will help. Include exact errors and any applicable screenshots, your SQL Server version number (including the build #), and the version of the tool you’re working with.

View Details

You’re planning to migrate to SQL Server 2022, and you want your databases to be faster after the migration.

This is NOT a blog post about how to migrate – that’s the same as it’s been for a long time. Go build the new 2022 servers, and use log shipping or database mirroring to sync the old and new servers. (I’m not a fan of using Distributed Availability Groups to do version upgrades. You can, but it is a heck of a lot of moving parts to set up for a one-time migration.)

This is a blog post about what to do after you migrate:

  1. Turn on Query Store, but make no other changes to your databases (including compatibility levels)
  2. Gather a 1-2 week baseline of performance metrics and query plans
  3. Switch some (but not all) databases to SQL Server 2022 compatibility level
  4. If users are unhappy with performance, use Query Store to identify plans that got worse
  5. Get relief for that query quickly, possibly with 2022’s new ways to fix performance without changing the query

Let’s go into details on each one of those.

Stage 1: Turn on Query Store.This new-in-2016 feature is like a black box recorder for your query plans. It has a lot of weaknesses, but it’s still better than your game plan that did not include Query Store.

The goal here is to start capturing query plans as they are today, before all hell breaks loose. Compatibility levels change execution plans, and SQL Server 2022 has a lot of ways that it might change your plans. If performance gets worse, we’re going to want to see what the query plan looked like before our change.

If you’re migrating from SQL Server 2014 or earlier, you don’t have access to Query Store yet. That’s okay: you can still do the migration, but just make sure that Query Store is the first thing you turn on after you go live on 2022. (You might have heard that Query Store is on by default in 2022 – that’s misleading. It’s only on for new databases that you create from scratch – it’s not on for existing databases you migrate into 2022.)

If you’re migrating from SQL Server 2016, 2017, or 2019, turn on Query Store sooner rather than later – long before you actually do the migration project. This way, you’ve got the historical data when you’re actually running on the current version, before the database is moved to 2022.

To learn how to configure Query Store, watch this video from Erin Stellato:

In either case, once you’ve moved to 2022, don’t make any other changes to your databases at first – especially not compatibility level. SQL Server 2022 has options for compatibility level going all the way back to SQL Server 2008, so you should be able to forklift your databases over as-is, and just leave them there for a week or two.

Stage 2: After going live on 2022, gather a baseline.We want to get a crisp, clear picture of how the old compatibility level is working out for us on SQL Server 2022.

Whenever you change anything about an application – whether it’s a code deployment, new indexes, or a SQL Server version change – people are going to always say, “Hey, things are slower than they used to be.” They’re probably lying. They’re just taking advantage of the opportunity to pin the blame on you, Default Blame Acceptor, and that’s why I want you changing as few things as possible when you do the migration.

Things may actually have gotten worse for their specific query, or for the workload overall. Maybe we messed up a SQL Server configuration, missed a trace flag, or the server hardware isn’t quite what we thought it was. (True story: a recent client’s new server was accidentally provisioned on the slowest possible storage instead of the fastest, so of course their upgrade went poorly.)

Do your normal investigative troubleshooting, and you can even use Erin’s tips in her video on how to use Query Store to track down query plan changes. However, during this stage, do not upgrade the database’s Compatibility Level to fix one query’s performance. Doing so will change the performance of many other queries, some for the better and some for the worse, and you’re not prepared to troubleshoot that right now. If people are complaining about one query, troubleshoot that query. If people are complaining about the whole server, troubleshoot the whole server – but leave compat level where it is for 1-2 weeks.

Stage 3: Change databases to 2022 compat level one at a time.Compatibility level is a database-level setting. You can see it by right-clicking on a database and going into its options, or by looking at the compatibility_level column in sys.databases.

It’s database-level because it’s possible that some of your databases will perform better on newer compatibility levels – but some of them may not. That means you should take the angriest users, the ones who are the most pissed off about slow performance, and try setting just their databases over to 2022 compat level.

It’s a simple one-line change to change to , as the documentation illustrates:

SELECT GETDATE(), compatibility\_level FROM sys.databases WHERE name = 'StackOverflow';ALTER DATABASE [StackOverflow] SET compatibility\_level = 160; “Wait – that’s two lines, not one,” you say, pointing your Cheeto-dust-encrusted finger at the screen. Well, the change is one line, but I want you to note the prior compatibility level and the date/time that you changed it – because you might need to roll back. Don’t worry, rolling back is as easy as running that same ALTER DATABASE command, but with the old compat level instead of the new one.

You can make this change whenever you want, without taking the database offline, but there’s a catch: it clears the plan cache for that database. That means you’re temporarily susceptible to parameter sniffing issues as SQL Server suddenly builds new query plans for this database.

Stage 4: Troubleshoot reports of slow performance.Most of your queries are probably going to go faster after the change. But what’s most? 90%? 99%? 99.9%? Even if just 0.1% of your queries slow down, that’s still a heck of a lot of queries to suddenly have to troubleshoot – especially when users often don’t even know which query they’re talking about. They’ll put in frantic help desk tickets that say things like “The customer screen is slow!!1!” and “The import process is down!!one!” and “My keyboard is filled with Cheetos dust!”

If tons of reports of slowness come in quickly, don’t be afraid to change the compatibility level back to the prior one. It’s a safe, quick, easy way to make the screaming stop. And… just stop there. If users are happy enough on the old compatibility level, leave it there.

However, if the slow query complaints come in at a rate that you can handle, and you’re seeing performance improvements that you wanna keep in other areas of the app, then it’s time to roll up your sleeves and do troubleshooting on the slow queries.

One of the easiest ways is to ask Query Store, “What query plans have gotten worse?” In SSMS, go into the database, Query Store, and then run the Regressed Queries report.

As soon as the report opens, you’re going to need to change the configuration, because the defaults are wrong. At the top right of the report, click Configure. Here’s what the defaults look like:

By default, it’s showing total duration – so queries that ran more often during a time window will show artificially higher on the graph – when the real root cause is that they’re running more often. Me, I like changing “Based On” to “Avg”.

Then, down at the bottom of the window, change “Minimum number of query plans” from 1 to 2. We’re looking for queries whose plan actually changed (perhaps due to the new compat level), not just slowed down. Click OK, and view the report.

The top left window lists the regressed queries, with biggest impact to smallest. As you click on each query, the top right window will update to show the performance of various plans for that query. Remember how I asked you to save the prior compatibility level, and the date/time that you changed it? We’re concerned about queries whose plan changed after the time that you changed the compatibility level. That indicates a query whose performance may have been adversely affected by the new compat level.

Stage 5: Get relief for that slow query.I’m going to list these from easiest to most time-consuming:

Option A: forcing an older plan. While you’re in Query Store’s Regressed Queries report, one of the easiest ways to get temporarily relief is to click on the query plan you used to get with the prior version of SQL Server, then click the Force Plan button on it.

I said it was easy. I didn’t say it was good.

When you force a plan, that doesn’t mean it’s going to perform well with all possible parameters for that query. This is especially true for queries that keep changing plans for valid reasons, like the example at right. That query’s got 5 different plans, and genuinely needs them. If I force a single plan for it, but my data has outlier parameters, I’m probably gonna get performance complaints from those users. We cover better ways to fix those in my Mastering Parameter Sniffing class, but that’s outside of the scope of this blog post.

Forcing a plan also means if a better option comes along later, like En Vogue’s lovin’, you’re never gonna get it. The whole reason you upgraded compat levels was to get better performance, but that query plan is stuck in the past. You can revisit them later by going into Query Store’s Queries with Forced Plans report – and I’d recommend going back in there every couple/few Cumulative Updates. Microsoft improves query plan behavior over time, so it’s possible that by unforcing a plan later, you’ll get better plan options.

Besides, you’re going to want to go into that Queries with Forced Plans report anyway because query plan forcing can fail, plus the query may change over time. As the query changes, the forced plan will no longer be relevant (because it’s for a query that no longer exists.)

I do still like forcing plans – and I wanna tell you about it because it’s quick and easy – it just has drawbacks, so we need to keep going with more options.

Option 2: give SQL Server hints for the plan. Let’s say that in SQL Server 2022 compat level, SQL Server decided to do something in the query plan that made performance worse instead of better. Let’s say it used batch mode processing on a rowstore index. If you want to disable that behavior, you can add a hint to the query without touching the query itself.

This is called Query Store hints, and David Pless has a tutorial on it. It’s not as easy as forcing a plan in the Query Store GUI. You’re going to have to get the query’s ID from Query Store, then apply the query hint you want using sp_query_store_set_hints.

It does involve work on your part, but … it’s still faster than fixing/tuning the query. As soon as you start changing the query itself, you’re probably dealing with getting approval from different folks in the company, getting it into source control, testing it, getting it deployed, etc. Query Store hints are instant, presto, in production. I can’t imagine how that could go wrong.

Option III: fix/tune the query. This takes the most work, but I’ll be honest: as a consultant, it’s the one I do the most often. Usually when I pop open a query that people are complaining about, I say, “Okay, here’s why it’s not performing well, and if I change this, this, and this about the query, it’ll go dramatically faster than it used to, and it’ll get a better plan overall.”

This is the option that doesn’t just bring performance back to its prior levels – it makes performance better, and after all, isn’t that what we want? (Honestly: no, a lot of people just want it back to the way it was, and that’s why this is the last option.)

SUM(MARY)When you’re preparing to migrate to SQL Server 2022:

  1. Turn on Query Store, but make no other changes to your databases (including compatibility levels)
  2. Gather a 1-2 week baseline of performance metrics and query plans
  3. Switch some (but not all) databases to SQL Server 2022 compatibility level
  4. If users are unhappy with performance, use Query Store to identify plans that got worse
  5. Get relief for that query quickly, possibly with 2022’s new ways to fix performance without changing the query

But while you’re in those final two stages, pay particular attention to the bold words. If users aren’t complaining about performance, move on to the servers where they are complaining about performance. Every server has queries that need to be tuned, and you need to focus on the ones that users will actually appreciate.

View Details

This one’s broken up into two parts because I took a bio break mid-stream:

  • 00:00 Start
  • 03:04 Clippy: Hey Brent, you are the best!!! Can you share us more about your roots? What’s the origin of your family name and where does it comes from?
  • 04:15 I_ALSO_WANT_A_FERRARI: Hi Brent, first of all thank you for all your good advices. During a batch I can see a heavy CPU load, in the perf monitor the
  • compiles are +/- 80% compared to the

  • batch requests. Too much. Most of the compiles are coming from TVP as param for a SP. Is this a bad practice?

  • 06:52 Sid V: Is their better value for the production DBA to go deep (knowledge) in their field or go wide (knowledge) in their field? What are the common examples you see of going deep and wide?
  • 10:38 Curious DBA: Hi Brent! Do you recommend manually configuring the pagefile.sys size and drive(s) it resides on when configuring new SQL Servers, or is that something you let Windows handle? If you do configure it, how do you determine how much size to allocate to it?
  • 11:33 Jaime Sommers: Is there a good way to determine what percent of queries are single threaded vs multi threaded for the purposes of knowing if we have too many cores / licensing.
  • 13:07 Q-Ent: Hi Brent . How do you imagine your life at your retirement. I assume for us, your followers will be “Brent Ozar Unlimited Last Update 2 years ago” :D. Do you prepare any successor for this empire !!!! Love your Job and your life perspective.
  • 14:03 gserdijn: Hello Mr Brent, Microsoft documentation on SET ARITHABORT for all versions states: “Setting ARITHABORT to OFF can negatively impact query optimization, leading to performance issues.” Why is that? Is the Cardinality Estimation so fragile?
  • 15:51 Yusuf: What are the best resources for learning PostgreSQL performance tuning?
  • 18:09 The Dyslexic DAB: Hi, We used to have a ‘special’ SQL license which meant that it matter if we installed Enterprise or Standard. Our licensing has changed and we now have dozens of Enterprise Editions that we can’t afford! Any advice or gotchas for downgrading from Enterprise to Standard? Thanks

And part two:

  • 00:00 Start, Twitch ad discussions
  • 00:40 DumbQuestionsRUs: Would you still recommend formatting drives to 64k?
  • 00:54 Shefatyah: What interesting stuff in the query plan XML do you wish was visible in the SSMS UI query plan?
  • 01:43 DantheSQLMan: Do you have any advice on working out of the country with SQL consulting?
  • 03:10 i_love_you_brent: Good morning Brent! We have 250 db on 1 instance.we use SIOS for failover on secondary. All dbs are on different versions with creepy procs for etl and etl data is stored in the same db.job runs every 15 to summarize data. Manager wants to separate 250 etl DBs on different machin
  • 04:38 Shefatyah: Sometimes running “EXEC sp_BlitzFirst @Seconds =10, @ExpertMode = 1” just runs forever but if we turn off expert mode and re-run it, it returns results instantly. Is this due to tempdb contention? Any troubleshooting tips? SQL 2019 Enterprise thanks
  • 05:40 NoobDBA: Hi Sir! Can you share with us, your biggest challenge on any consulting job that have you been into. Thanks!
  • 07:40 How do you eat rice with chopsticks?
  • 08:04 Yusuf: Is there a recommended way to run a SSMS query and then immediately run sp_blitzcache to analyze the most recent run for that query?
  • 08:53 Cara Dune: Which is better for office hour streaming? Youtube or Twitch? Why?
  • 10:02 ChopstickWizard: Probably a very silly question. When I write Select A.* from A INNER JOIN B On A.T = B.T and then someone else writes Select A.1 From A, B Where A.T = B.T Whose is better? Performance wise. so sorry if this is a very basic question
  • 12:26 EngineHorror: Have you ever run into the Halloween problem in any of the DMLs? Can one say that the recent versions of SQL Server don’t have it?
  • 13:48 i_love_you_brent: We have 250 dbs on 1 instance with etl and oltp together. is it worth spending time on separating those to 500 dbs 1 for etl and 1 for oltp. reports are timing out sometimes.
  • 14:40 ExtramileDBA: I have done tons of projects on SQL server and recently moved to a shop that is pro-MYSQL with SQL server only supporting ISV products. Do you know of any awesome MySQL conferences similar to the likes of Group By, SQL bits and Pass.
  • 16:08 Aleksey Vitsko: Hi Brent! With announced “failover from SQL Server 2022 to SQL Managed Instance” feature still being in private preview, do you think Microsoft will make this feature publicly available with one of future CU for SQL 2022 ? Just install CU and feature becomes available ?

I’m doing live streaming on my Twitch channel on Wednesdays & Thursdays this summer, and the recordings will go live later on my YouTube channel. I’ll take questions from PollGab, do live coding, work on the First Responder Kit, and write blog posts.

The stream will start at 8:15AM Pacific, 11:15AM Eastern, and you can see the time in your local time zone here. I’ll stream for around 45 minutes.

To get notifications when I go live, follow me on Twitch, or Google Calendar users can use this invite. See you in Twitch!

View Details

If you right-click on a database in SQL Server Management Studio, you get an option to set Compatibility Level at the database level:

When you upgrade SQL Server or you want to improve performance, which option should you choose? Should you always go with the newest compatibility level? If you have an old application, can you upgrade SQL Server but still keep the old compat level without the vendor knowing? Let’s hit the common questions.

What does compatibility level do?When Microsoft brings out a new version of SQL Server, they tend to keep the newest features only available in the newest compatibility levels. For example, SQL Server 2022’s Parameter Sensitive Plan Optimization (PSPO) is only available in databases running under SQL Server 2022 compatibility level.

That means if you’re taking a database that used to live on an older SQL Server, and you want to host it in SQL Server 2022, and you want it to have the same behavior that it’s always been used to, you should keep it on the compatibility level that it’s currently on. For example, if you’re hosting it in SQL Server 2016, and the database is currently at SQL Server 2016 compatibility level, then you could move the database to a 2022 server, but keep compat level on 2016, and the users shouldn’t notice the difference.

In reality, though, there are things inside SQL Server itself, at the server level, that will change no matter what your compatibility level is. For example, if Microsoft deprecates a feature and removes it altogether, that feature isn’t available even if you’re on older compat levels. (Hello, Big Data Clusters.)

Should I change compatibility level?If there’s a specific feature that you need that’s only available in some compat levels, then yes.

However, if you’re happy with performance, then no. Hear me out: changing your compatibility level can make performance worse instead of better. Sure, in some cases, it makes performance GREAT – but because all change = risk, then changing compat level when you’re already happy is dangerous.

How does compatibility level affect performance?If you migrated from SQL Server 2019 to 2022, here are ways that changing a database’s compatibility level can make things better or worse:

  • Cardinality Estimation Feedback can change a query’s estimated number of rows
  • Degrees of Parallelism Feedback can reduce the overhead of bad parallelism (most parallelism is good though)
  • Parameter Sensitive Plan Optimization can cache multiple query plans for the same query

In each version of SQL Server, different features are enabled under newer compatibility levels. Before changing your compat level, you should review what features are added when you change from your current compatibility level to the new one. This is a good starting point.

What should I measure before changing compatibility level?In theory, you should have a performance baseline of things like:

  • CPU, memory, and storage metrics
  • Your top wait types so you know what SQL Server is bottlenecked on
  • Which queries are using the most resources
  • Query plans of well-performing queries (because things might get worse, and you’ll wanna know what they used to look like back in the good old days)

Then, when people suddenly complain about performance, you can check your baseline to see whether things actually got worse, or whether your users had taken up eating shrooms. You could also track down which queries were NOW at the top of your resource-consuming query list, look at what their query plans USED to look like, and then figure out how to get back to the good old days.

Common ways to accomplish this are third party monitoring products, Query Store, or the First Responder Kit.

In reality, you’re not gonna do any of this ahead of time. So, when you change compatibility levels on the fly, and performance gets worse, you’re not going to have any answers.

Does that mean I shouldn’t touch compatibility level?No, not at all! You can change compatibility levels whenever you want, one database at a time. You can also change back instantly as well. You just need to be aware of when you made the change, what you changed, and communicate it to the rest of the team so they can roll your change back if necessary.

What compatibility levels are available?The screenshot at the top of the blog post was taken in SQL Server 2022, and even in this recent release, Microsoft supports compatibility levels going all the way back to SQL Server 2008. That’s kinda awesome, because it means that Microsoft is trying to keep old databases working great in newer versions of SQL Server.

In theory, that means you can take an old vendor application that was once certified on SQL Server 2008, and keep moving it to newer and newer versions of SQL Server. In theory, that means it’ll keep working the exact same way as long as you keep the same compatibility level – and hey, it might even get faster if you change to newer compatibility levels.

So, can I actually do that?Well, no. I mean you could, but you might get caught.

Here’s the thing: the vendor might be relying on a feature that’s no longer available in newer versions of SQL Server. I gotta be honest, that’s extremely unlikely, but it is possible. And if they are, and their application suddenly breaks, you can’t restore a newer SQL Server database to an older version of SQL Server.

So if you take your SQL Server 2008 server, back up the databases, restore them onto SQL Server 2022, and then start using the app – and people start complaining – you can’t restore those 2022 backups down onto SQL Server 2008, even if they’re still in the same 2008 compat level. You can only restore to newer versions of SQL Server, not older.

Therefore, you’re taking a risk when you move databases onto newer versions of SQL Server. Make sure the vendor actually supports the newer version of SQL Server, because you don’t wanna be the person that the vendor blames for their application not working successfully.

Want to watch me write this blog post?I streamed this blog post live if you want to get a rough idea of what’s involved with writing a post like this:

View Details

HONK HONK! It’s time for a fast round of answers to concise questions y’all posted and upvoted at https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:19 TheyBlameMe: Hi Brent. What is your view on using Dacpac diffs vs “old style” manual update scripts for deploying DB schema changes in dev-test-prod?
  • 00:52 Alex: Hi boss, I have an app that creates a new DB for each customer. All DBs (3K~) have the same structure. Is there a best strategy or an article you can point to consolidate all DBs into one huge DB. Is it a good idea? I’m trying to save on maintaining hundreds of databases. Thanks
  • 01:42 Perplexed: Had a vender application running a stored proc and it wasn’t working. Ended up using Profiler to capture error message and passing that to vendor to fix. Is there a better way to find error messages that procs are kicking out, but hidden by error handling in proc?
  • 02:31 Piotr: Is there anything comparable to first responder kit for PostgreSQL that you like to use when performance tuning in on that side of the fence? How hard would it be to write a first responder kit for PostgreSQL?
  • 02:56 HashMatch: Hey, Brent! I have a work superior who prefers to use several UPDATE statements instead of joins, to “keep track of row counts”. How do I best demonstrate this isn’t a good idea for performance?
  • 03:39 Steven: Hi Brent, in a nighlty ETL my friend has 2 sprocs updating 1 table in parallel. A page-level deadlock occurs randomly (1 in a 100 runs). Any tips or ressources on how to fix a deadlock at page-level while keeping the sprocs parallel? Thank you
  • 04:34 Piotr: Do you have any recommended tools for diff’ing two SQL tables for the purpose of showing the index differences between the two tables (DEV – PROD)?
  • 04:55 Björgvin: Do you ever see any issues with using windows mount points and SQL Server?
  • 05:29 TY: Hi Brent, in my job we often use the ROLLBACK of a transaction for testing purposes. Is there an easy way to rollback after two or more days, when the TRAN has been already COMMITED? Like a checkpoint where you can return to, but only for a single table or a database?
  • 06:04 Piotr: Do you think we will ever see FORCE_SHOWPLAN_RUNTIME_PARAMETER_COLLECTION in SQL2019 again? Is this feature worth upgrading from SQL 2019 to SQL 2022?
  • 07:01 Mickey: Hi Brent, I have a reporting query that runs under 10 seconds on other environments but runs for hours without finishing on this one environment. I’ve verified stats are up-to-date and the proper indexes are the same across all environments. Any other recommendations? Thanks!
  • 07:44 Gromit: Do you have a good way to fix high VLF count that doesn’t break log shipping?
  • 08:04 Nick Smith: Hi. Why might performance degradation of truncate tables in tempdb be seen after some time working in SQL Server 2019? There are no schema locks. I make look wait types trace in the current session, then there is nothing but SOS_SCHEDULER_YIELD and SOS_WORK_DISPATCHER
  • 08:37 LostInSpace: I have a developer using WAITFOR DELAY (10 – 15 minutes) to pause the iterations of his code instead of doing it in c#. I noticed them using sp_WhoIsActive with parms: @find_block_leaders = 1, @get_locks = 1, @get_additional_info = 1. It leaves suspended connections. good/bad?
  • 09:28 WorkinForDaMan: I’m the DBA for a city with a hybrid environment (on-prem and Azure VMs). While I was on leave, IT pushed 2016 AZC+GDR build instead of, SP3+GDR. I’m comparing both for diffs but wonder if you’d suggest reverting to SP3+GDR since we don’t have managed instances. Thank you, sir!
  • 10:07 Haydar: Do you have any recommended books / courses for sizing azure vm’s for lift and shift of SQL Server?
  • 10:53 Doc: Do you encounter peeps that live on the cruise ship in retirement? Is this an option for you?
  • 11:30 Ron Howe: What diagnostics would you recommend for a SQL Server that is fully 100% CPU throttled during query execution due to a “bad” query plan and you can’t get a SQL connection as such and a hard reboot seems the only solution?
  • 12:03 Nortzi: Hi Brent, recently a SQL statement with a begin tran and commit tran was executed from ssms and returned a results message. We had a blocking issue the next day. Turns out this query was still technically running and never finished. What do you think could have caused this?
  • 12:56 TY: Hi Brent, it seems like you know everything about SQL Server, or at least it seems like it. Can you do a short session with something that you don’t know much about and lead us through the process of learning it. It would be very beneficial to see how you build your knowledge. Ty
  • 13:56 marcus-the-german: Hi Brent, do you recommend that the sql server instance collation is the same like the user databases. If yes, how should we deal with databases which have a different collation?

View Details

Some of the questions y’all post at https://pollgab.com/room/brento have easy one-line answers. Let’s knock ’em out:

George: Hi Brent, what recently has been the most challenging/surprising/new-to-you performance issue you have encountered?

SQL Server 2019’s slowdowns. I spent days working on that.

RoJo: Have you used Distributed AG as a way to upgrade major versions of SQL server without downtime? Seems like a nice way to try it out on a second site before a switch. Any concerns? Maybe jump from 2016 to 2019, or 2022 to big a jump? Cheers

No because it’s so much work to set up.

ConsultantWannabe: I’m a generalist trying to make the jump into the consultant role, I don’t want to be “a jack of all trades”. How should I start finding that niche (or that “expensive” thing to stand next to, apart from SS)? Do you think just asking around to the guys in suits is a good idea?

Ask executives what technology problem they can’t solve with their current staff.

Ive_Got_Heaps: Hey Brent, Our DB is loaded with heaps as our ERP system doesn’t utilize primary keys (begins crying). My plan is to create clustered indexes on existing columns where possible, or create an Id column for tables where no existing column can be used. Is this a sound approach?

Ask the ERP vendor. If it’s an in-house app, watch this.

Yevgeny: What are the top causes of data file corruption for SQL Server on a Windows cloud VM and how do you avoid them?

In the cloud, you don’t get root cause analysis from your vendor. Do backups and high availability (like AGs for automatic page repair.)

SQLrage: In 2019, can statistics updates on a table cause an execution plan to be recreated for a parameterized proc that hits the table but does not use that updated statistic in particular? Trying to better understand why plans regenerate automatically.

Read this and do a test.

Bart: Is there any harm in deleting Extended Properties of a table column? I inherited a database that’s been converted from MS Access into MS SQL several years ago and I think the extended properties are a result of that conversion.

What’s the benefit in deleting them? Why risk it? Who cares?

My latest toy, heading out for engine work firstPiotr: What file system folder convention do you like to use when locating data files / log files for a new SQL DB?

\MSSQL\DATA

Chetan: Which nice car did you buy recently? What do you drive now?

A 1964 Porsche 356 coupe, which is getting its engine checked out first before I take it on any road trips. Until it’s done, and because it’s springtime, I mostly drive my Speedster replica.

MacAries: I had an On Prem 3 CTE then join for result query that ran subsecond, but coming from Azure Function that sent multiple and crippled the on-prem server to a 20 result /minute nevermind the lock and batch waits is their some basic translation that azure needs to get the query run?

Read this or watch this.

Will Marshall: Do you run into any common performance issues with SQL always encrypted?

I’ve never had a client use it.

Haydar: What is the best way to copy a few tables from SQL Server to PostgreSQL?

I would ask this guy.

CB: Hi Brent – It seems SQL functionality isn’t supported in SQL task editor. Statement: Declare @sql nVARCHAR(max) Error: The Declare SQL construct or statement is not supported. Is there a solution to that?

I don’t know what the “task editor” is.

Will Marshall: What are the best courses / books for learning SQL Always ON?

I haven’t seen any that were updated with what’s new in SQL Server 2019, 2022, or Managed Instances Link.

Bocephus: For network perf testing between two windows nodes, what tools do you like to use?

Copy a large file like a backup.

Hal Jordan: What should we look at when OS pages per second paging rate is high for the bare metal SQL Server 2019 instance?

Attend this class.

Mirza: Discussion happening in the company about automating SQL patching on clusters using Powershell and SCCM. Both PS script and SCCM are owned by the server team. Does the DBA team lose control and does it matter? What is your experience/opinion regarding automating SQL patching?

Read this.

Kyle: Hi Brent! What are the best practices for restarting your SQL service on an HA system? Is there any way to do it with causing any downtime?

No, all restarts will cause downtime, even for cluster and AG failovers, so for minimal downtime, use clusters and AGs.

SQL_Developer_Admin: If there is left outer join, then why there is right outer join as well, if we could just swap the sides of the tables. Any scenario you know where only left join can be used or right join can be used.

Sometimes it’s nice to have multiple tools to approach the same problem from different angles.

Eyvindur: You mentioned caching as a possible solution to lessen the load on SQL Server. Are triggers are good solution for cache invalidation?

The idea of caching is to lessen load. Do triggers add or lessen load on the database?

Eduardo: Do you see any RDBMS disruptors threatening to steal Microsoft / Oracle market share in the near future?

If by “near” future you mean 5-10 years, yes, Postgres and AWS Aurora.

ChopstickWizard: Been mulling this over for sometime. There are instances where I want to recommend a product to a team, like example : Cockroach db, mage.ai etc. But the problem is, they seem “non enterprisey” just by their name in case of “cockroach” or mage.ai’s tag line. Have you faced this?

You mean names like ChopstickWizard?

View Details

Post your questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me answer.

Here’s what we discussed today:

  • 00:00 Start
  • 01:40 prasad: Hi Brent, I want to become a full fledged database architect. I have been reading and practising lot of stuffs here and there, but no certain path. I also subscribed once to ur master class bundle. can you guide me on a proper path for the same? Thanks in advance
  • 04:57 ExcitingAndNew: Hi Brent, what is your opinion on the practice of inserting SQL comments into SQL requests as tags to allow DBAs to track the requests in the server ? (I’m talking about comments for instance just after SELECT/INSERT/UPDATE/DELETE to force SQL Server to keep them everywhere)
  • 05:40 DGW in OKC: What is your opinion on the practice of a manager who consistently assigns DBA tasks to an employee who is marginally proficient at DBA work and is not really that interested in this discipline anyway?
  • 08:08 Fjola : sp_BlitzFirst shows the top expensive query of type : statement. It’s unclear which app/sp is generating this query. What is the best way to track down the app / sp generating this query / statement?
  • 10:05 Chris: Have you ever had manually created statistics either be a root cause or the final push needed to cross the line?
  • 10:53 CKI: How to get history of most recent queries executed with username in SQL? Auditing is not an option. Thank you!
  • 11:50 Piotr: Do you have a recommended method for adding notes to a given NC index (i.e. why this index is needed, which app uses it)?
  • 12:38 Perplexed: What are your thoughts on using PERSIST_SAMPLE_PERCENT to force all future UPDATE STATS to use a specific sampling? I just started using this on a very large table that was not getting stats right after updating the stats.
  • 14:02 UncleFester: When running Select /Count() SQL was using an index, returning only 47 mil rows of 95 mil in the table. Rebuilding the index/statistics was no help. Dropping/recreating the index solved it. Can I really trust Select * or Select Count(*) to return all of the rows in the table?
  • 14:56 RoJo: Debate rages here on what login to use for security: AD/Windows or SQL direct. Is either more secure? or if equal, do you prefer one and why? Thanks dude

View Details

Ever wonder how fast people are adopting new versions of SQL Server, or what’s “normal” out there for SQL Server adoption rates? Let’s find out in the spring 2023 version of our SQL ConstantCare® population report.

Out of 3,002 monitored servers, here’s the version adoption rate:

The big 3 versions are all within 1% of the last quarter’s numbers:

  • SQL Server 2019: 33%
  • SQL Server 2017: 19%
  • SQL Server 2016: 28%

On the other extreme:

  • SQL Server 2022: 2% – which is right on track with 2019’s adoption rates after it came out. It’s not low at all – it’s right in the same ballpark.
  • Azure SQL DB: 1%
  • Azure SQL DB Managed Instances: 2%

Just 13% of the population are running unsupported major versions (2014 & prior).

Here’s how adoption is trending over time, with most recent data at the right:

In other news, we do actually have 6 folks now running SQL Server on Linux! It’s a total of 32 SQL Servers, a mix of 2017 and 2019, running on a mix of Ubuntu and Amazon Linux. That’s about a 1% adoption rate. Only 4 of those are Dev or Express Editions, too. I’m still feeling pretty comfortable with my 2018 prediction that in 2026, <5% of SQL Servers would be running on Linux.

Other interesting tidbits:

  • 8% of SQL Servers are in a failover cluster
  • 23% of SQL Servers have Availability Groups enabled (not necessarily using it, it’s just enabled)
  • 6% of servers have Filestream enabled (not necessarily using it, it’s just enabled)
  • 34% are fully patched to the latest possible Cumulative Update (that’s amazing!)

34% of servers are fully patched to the latest possible Cumulative Update. That’s awesome! Nice work, y’all. My first thought was, “Oh, I bet the old versions like 2012 are fully patched, but the new ones aren’t patched because the patches keep coming out.” Nope, it’s actually the opposite: the most-currently-patched folks are on 2016 & 2017. The least-patched are the unsupported versions that haven’t had patches in forever. Disappointing.

Only 7% of SQL Servers are on unsupported versions or builds. That’s awesome too! Keep up the good work on patching, y’all.

View Details

It’s time for summer school!

I’m doing live streaming on my Twitch channel on Wednesdays & Thursdays this summer, and the recordings will go live later on my YouTube channel. I’ll take questions from PollGab, do live coding, work on the First Responder Kit, and write blog posts.

The stream will start at 8:15AM Pacific, 11:15AM Eastern, and you can see the time in your local time zone here. I’ll stream for around 45 minutes.

To get notifications when I go live, follow me on Twitch, or Google Calendar users can use this invite. See you in Twitch!

View Details

You, dear reader, are most likely a Microsoft SQL Server user – either a DBA or developer.

Set your pencil down for a second because you’re not going to learn about a Microsoft product today, nor are you going to learn something that is going to be immediately useful to you in your job. Today, I’m writing about a completely different product just to give you a better insight on what else is out there.

Our SQL Server monitoring app, SQL ConstantCare®, uses AWS RDS Aurora PostgreSQL as its database back end. I wrote about that design decision five years ago, and since then, we’ve been really happy with both PostgreSQL in general and AWS Aurora in particular. We just didn’t have to spend time worrying about the database layer – for the most part, it just worked, in the same way Microsoft Azure SQL DB just works.

No matter what database platform you use, costs are split into two main parts:

  • The storage layer – where you pay for how much you store, and how many accesses you do (reads and writes)
  • The compute layer – where you pay for CPU & memory for the servers to process your ugly queries

Traditionally, us data people have wanted the fastest storage we could get, and the most compute power we could get. That led to problems with management because we bought really good stuff, and then… it usually sat around idle, unused. We had to pay a lot to handle the peaks of our workloads, and then we were locked into expensive stuff that rarely got hit hard.

Serverless can reduce those costs while simultaneously handling more bursts.To help reduce costs and improve flexibility, several years ago, AWS introduced Aurora Serverless. Instead of paying for fixed server sizes (like 8 cores and 60GB RAM), Aurora Serverless:

  • Watches your query workload
  • Automatically adds & removes CPU & memory on the fly
  • And reacts automatically in milliseconds without dropping queries

Not minutes. Not seconds. Milliseconds. That’s bananapants. You just define a minimum and maximum size for your database servers, and Aurora automatically handles the rest, independently, for each replica. Instead of provisioning an 8-core, 60GB RAM server, you could say you want your config to swing anywhere from 2 cores and 4GB RAM all the way up to 64 cores and 128GB RAM. (More on the exact provisioning later.)

Somebody at Microsoft is going to be tempted to pipe up, “Yeah, we have serverless in Azure SQL DB too,” and I can’t help but respond in meme form:

Yes, that’s actually in the documentation, and it’s why you’re not hearing a lot of buzz about serverless here in the Microsoft & Azure communities. Azure balances load in minutes, not milliseconds, and drops connections at the worst possible time – when you’re under heavy workloads and the server isn’t able to keep up.

I suppose that’s serverless, in the sense that you lose the database server temporarily? Let’s move on.

Aurora Serverless was a perfect fit for SQL ConstantCare®.SQL ConstantCare® consists of a small app that clients install and point at their SQL Servers. Once a day, that app polls all of their SQL Servers, exports diagnostic data to JSON files, encrypts it, and sends it to us. We can’t predict when it’s going to happen – it’s based on the schedule that users set up on their end, which tends to be even-hours (like noon or 4PM local time in their own time zone.)

When the files come up to us in AWS, we:

  1. Decrypt & extract them, and then load their contents into a database
  2. Run diagnostic queries, checking for problems, and build a list of things to warn them about
  3. Send them emails with advice

That application logic layer has been serverless (AWS Lambda) all along, and I wrote about that design decision as well. That’s paid off really well as we scaled to thousands of client servers because the workload is really bursty. We don’t wanna pay for lots of app servers to sit around idle most of the time, but when client files come in, we want to process the data as quickly as practical.

The problem right from the start? The database layer! AWS Lambda would see lots of incoming files all at once, spin up lots of workers to process all those files, and then – wham, all those workers would try to tackle the database server at the same time. Richie had to work hard to smooth out the peaks, or else we just kept DDoS’ing our own database server.

By switching to Aurora Serverless, the database could now better handle bursts of incoming files – while simultaneously cutting costs by downsizing capacity for the hours per day that we sat mostly idle.

When you create serverless replicas, you size them in Aurora Compute Units (ACUs). One ACU = 1 core and 2GB RAM. Because we wanted to make sure it worked, we picked:

  • Min replica size: 0.5 ACUs (that’s 1/2 a core and 1GB RAM)
  • Max: 32 ACUs (that’s 16 cores, 64GB RAM)

And then sat back and watched the replica automatically handle workloads.

Aurora resizes our database servers FREQUENTLY.Here’s an average of the primary writer’s ACUs over a 24-hour span, in 1-minute intervals:

Don’t worry about the time zone or peak hours – just think about this being a 24-hour time span. On average, we have a few different bursts per day, but we generally range from around 2-3 ACUs (cores) up to around 28 ACUs (cores). But here’s where it starts to get wild – instead of looking at averages, let’s look at the MAX in each minute range:

Aurora is frequently slamming the gas pedal, taking us right up to 32 cores! We’re maxing out at 32 cores all the time throughout the day. And conversely, the min in each minute:

It’s slamming the brakes right down to 1-2 ACUs all the time.

Lemme rephrase those 3 charts: in many one-minute time spans of the day, our Aurora database server scales up and down automatically from 1 core to 32. All day long. In fact, it’s rare to have a 15-minute time span where Aurora didn’t ramp capacity up and down like crazy. Here’s the same set of charts in 15-minute intervals – first, maxes:

In most of the day, in any given 15-minute time span, we were hitting 15-32 cores. But for mins:

It dropped right down to 1-2 cores.

Again, this is night-and-day different to what Azure is doing. Microsoft’s all, “Hey, let’s think about this for a while and transition up and down over the span of a minute or two.” Amazon’s reacting with lightning speed, so as each query comes in, it gets the power it needs and our apps don’t notice the difference.

Admins have to ask new questions.Because Aurora’s reaction time is so fast, it opens up totally new questions for performance tuning and cost management.

“Are we doing the right database maintenance?” Resource-intensive queries literally cost you money. We were spending around $50/day for storage throughput at one point, and one day’s cost suddenly shot to $250. After digging into AWS’s Performance Insights (which is fantastic, by the way), we determined that a surprise automatic index maintenance job had cost us $200. That experience changed the way we think about index maintenance, and for SQL Server admins, that would be especially eye-opening. Are you sure you need those index rebuilds? Can you prove that the server is actually getting faster for your money? Odds are, it’s not.

“Should we raise or lower the max ACUs?” If we raise it, then resource-intensive queries might be able to finish more quickly – but scaling up compute power doesn’t always result in a linear speed-up of queries. Just because you go from 16 cores to 32 cores doesn’t mean big queries finish exactly 2x faster. The question morphs into, “How low can we go? How low can we set the max without hurting our most valuable queries?”

“When we change ACUs, how does that affect IOPs?” When you add more ACUs, you get more memory available to cache data, which means you hit storage less frequently. When you reduce ACUs, you’re likely going to hit storage more. There are no dials to set for storage performance – Amazon manages that for you automatically, and just bills you for every IO you do. There’s no easy across-the-board answer here, either – the answer is going to depend on your own workloads. For SQL ConstantCare®, we’re constantly importing new data and querying it, so cache is less useful to us.

“Does serverless make sense for our workloads?” Does this scale up/down, cost up/down actually benefit your application either in terms of lower cost, or faster performance? For our particular workload, it was really funny when we first switched over – Aurora Serverless was almost exactly the same cost as our previous pre-sized, inflexible servers, hahaha! However, by tuning our max ACUs, we could more easily find a sweet spot where we could reduce costs without harming performance.

But here’s my favorite part of Aurora Serverless: it gives us the ability to run new product experiments without worrying about capacity. For example, since the very start, I’ve always wanted to have a completely free tier of SQL ConstantCare that alerts you about the most vital issues, like missing backups, database corruption, or an urgent patch. Before moving to Aurora Serverless, I didn’t want to test that out because a huge wave of free adoption might cause us database performance nightmares. Now, the database server isn’t holding us back from those issues. (So stay tuned for some fun experiments!)

“Does migrating from SQL Server to Postgres make sense?” By this point of the post, you might be jealous of this cool technology. Remember, though, that right at the beginning I told you that today’s learning wasn’t going to be too relevant to your current job. You don’t really wanna change an entire application’s back end from one database platform to another, regardless of how easy Babelfish might make it seem. Back end migrations rarely make sense. However, I just wanted to talk about this technology today so you could see what’s going on in other database platforms.

Besides, Microsoft’s surely working on similar capabilities for Azure SQL DB. I love how cloud databases turned into an arms race because they’re a real differentiator for cloud vendors.

If you liked this post, you’ll probably enjoy Ed Huang’s musings on building a database in the 2020s. He asks, “If we were to redesign a new database today from the ground up, what would the architecture look like?” To be frank, it wouldn’t look like Microsoft SQL Server, and between his post and mine, you’ll understand why. I’m not saying SQL Server is dead, by any means – but if you’re a developer building new-from-scratch applications in the 2020s, SQL Server probably isn’t your first choice, and that’s why.

View Details

It was a dark and stormy morning, on the last day of my Panama Canal cruise. Before I perished, I sat down to answer your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:36 ClippyTheDBA: Hi Brent. How you keep up-to-date with technology in general and in SQL Server specifically?
  • 02:56 Björk: Should foreign keys be indexed from day1 or only when performance issues arise from lack of a NC index on the foreign key?
  • 03:55 ClippyTheDBA: Hola Brent. If you just started your consulting business, what thing(s) you would change or do differently (based on your current consulting business experience)? [Kind of Lessons Learned]
  • 06:00 Haydar: What bad stuff can we look forward to once SQL Server hits the max size for a data file? Any interesting stories of this happening in the wild?
  • 06:52 Eduardo: How do I find the worst performing query for a given app using the first responder kit?
  • 08:51 Netanel: Is it safe to overlap invocations of the tools in the first responder kit (i.e run sp_blitzindex at the same time of running sp_blitzcache, sp_blitzfirst etc)?
  • 09:48 Alex: Hi guru, Regarding your last office hours where you talked about 2022 version. I was planing to upgrade from 16 to 22, now you got me thinking. Should I upgrade to 19 instead as 22 is full of bugs?
  • 10:56 Gopher: What criteria do you use when picking cruise ship line A vs B?
  • 13:09 AGAnyday: I am in a shop with backup policies dictating full backups daily, Colleague DBAs say there was a research policy informing that course of action. What is the best gentle approach to convince the management to resort to full backups for weekends then do differentials every night?

View Details

Is your company hiring for a database position as of April 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Off the coast of Costa Rica, I went through your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:30 gotqn: In SQL Database we have “sp_invoke_external_rest_endpoint”, but in SQL Server 2022 still have not. Is using SQL Server Machine Learning (sp_execute_external_script) a good alternative or nasty hack?
  • 02:19 Chase C: If you had complete authority to focus Microsoft on fixing or adding a feature to SQL Server, what would you choose?
  • 03:52 I like hot pot: Hi Brent, is any of your client using Sql Server 2022 in production and if yes, how bad is it?
  • 04:56 Peter: Hi Brent, our devs are writing parameterless table functions opposed to views. Beyond the extra syntax required to create them is there a demonstrable downside or should I just step away even though I think it is hiorrible.
  • 05:36 Jr Wannabe DBA: Hi Brent, what do you think it is the best way to trigger (fire and forget, do not wait for result) an external application action from an INSERT into a SQL table? Looking for a direction, not full solution. Thanks in advance.
  • 06:36 Mr. SqlSeeks: Upgrading our Azure VMs. Our folks suggest using a VM size that has burstable IOPS. I think about troubleshooting performance issues and scalability testing, having to figure out if things were executed during a burst or not. I feel like I want consistent IOPS in Prod. Thoughts?
  • 07:49 Mike: If hosting AlwaysOn Availability Group on Azure VMs – can I have, say, 1 server (replica) with 32 vCPU, 2nd server with 4 vCPU, and 3rd server with 8 vCPU? Will AG with different size replicas work fine? And, can this affect data synchronization in some way?
  • 09:03 chandwich: Hey Brent. Have you ever had a client refuse to let you install your sp_Blitz stored procedures? If so, how did you handle that situation?
  • 10:18 TheyBlameMe: Hi Brent. What’s your preferred strategy when updating a limited downtime production system from an int PK parent table to bigint?
  • 11:42 Netanel: When is a high perfmon value for skipped GHOST records per second ever a concern? sp_BlitzFirst is reporting 53k skipped ghost records per second.

View Details

I’m running into something that I’m having a hard time believing.

A client was hitting CPU issues during load testing, and they swore all things were equal between their SQL Server 2016 and 2019 environments. The 2019 box was having CPU pressure issues that didn’t show up on the 2016 box. I’ve played this game before, and every time, the root cause has been different configurations between the two servers.

However, this time, not only were the servers the same, but I’m even seeing this same behavior with a simple query that I can reproduce on any 2016 vs 2019 setup. I haven’t tested on any other versions yet, but after a day of banging my head against the wall, I figured it was time to bring in the smart people – and that means you, dear reader.

Take any two identical servers, and I do mean identical – same CPU speeds, same power savings settings – and run this setup script. We’re creating a database in 2016 compat level just to compare the exact thing across all versions:

CREATE DATABASE TestCompat2016;GOUSE TestCompat2016;ALTER DATABASE CURRENT SET COMPATIBILITY\_LEVEL = 130;DROP TABLE IF EXISTS #Numbers;GOCREATE TABLE #Numbers (Number INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,TestString VARCHAR(100));GOINSERT INTO #Numbers (TestString)SELECT TOP 5000000 'Hi'FROM sys.all\_columns ac1CROSS JOIN sys.all\_columns ac2CROSS JOIN sys.all\_columns ac3;GO Then turn on statistics time, and run this query:

SET STATISTICS TIME ON;GOSELECT TOP 1 UPPER(LOWER(LTRIM(RTRIM(CAST(Number AS NVARCHAR(100)))))), SUM(1) AS recsFROM #NumbersGROUP BY UPPER(LOWER(LTRIM(RTRIM(CAST(Number AS NVARCHAR(100))))))ORDER BY SUM(1) DESC, UPPER(LOWER(LTRIM(RTRIM(CAST(Number AS NVARCHAR(100))))))OPTION (MAXDOP 1);GO 3 The query’s terrible, of course, but it’s designed to do a fixed amount of CPU work every time. We’re not disk-bottlenecked – the tiny numbers table fits easily in memory. You’re going to be tempted to change the table design or query design, and you’re absolutely welcome to, but make sure the query is CPU-bottlenecked, not read-bottlenecked.

Compare the CPU time (not duration) across SQL Server versions. Because I’m paranoid, I built a brand new Windows Server 2016 box from scratch up in the cloud, and installed two instances of SQL Server on it. Left hand window is SQL Server 2016, right hand window is 2019 RTM – don’t run them at the same time, obviously, because that would screw up the CPU availability:

SQL Server 2019 uses 5-10% more CPU time to execute the same query.It’s not just single-threaded queries, either – if I let the query go parallel by removing the MAXDOP 1 hint, 2019 is still slower:

You’re also going to be tempted to say, “Just change the compat level, query, or indexes to make the whole thing go faster on 2019” – but that’s not the point, because often we can’t tune an entire running workload. (In this demo case, 2019 compat level actually works beautifully, dropping the CPU time down by about 1/3, and I wish the client’s case was that easy. They already tried that before they called me. Bummer.)

You’re also going to be tempted to say, “I bet it’s fixed in a 2019 Cumulative Update,” in which case, check out this wider screenshot. The far right window is 2019 CU19, the most current one, and it exhibits the same higher CPU usage as 2019 RTM:

You might even be tempted to say it’s the new lightweight query profiling – try turning that off:

ALTER DATABASE SCOPED CONFIGURATION SET LIGHTWEIGHT\_QUERY\_PROFILING = OFF; And at least in my tests, it makes no difference.

That’s where you come in.If you have access to absolutely identical environments (or different versions installed on the same base hardware), are you able to replicate these findings? Does the same query use more CPU time on 2019 than it did on 2016? The best evidence for this is a side-by-side screenshot of the same query’s output across the different versions.

For our own evil purposes, 2017 doesn’t really matter (because you’ve gotta get to current versions anyway), but if you want to test on, say, 2016 vs 2022, you’re welcome to. In our brief testing, we’ve seen 2022 exhibit the same CPU problems as 2019.

I wouldn’t use this case as evidence that 2019/2022 are “bad” by any means – they’re fine. It’s just helpful for folks to understand, when they’re doing capacity planning for new versions, that they may have to buy more licensing for the same server at upgrade time. In this particular client’s case, we’re probably going to have to bump from 8 cores to 10 cores in order to handle the same workloads – in their cases, the CPU difference is closer to 20%.

View Details

You’ve been working hard all month to get through our newest class, Fundamentals of PowerShell for DBAs. This week, it all starts to come together as you put together PowerShell plus SQL Server to automate tasks on a regular basis:

  • March 27, Mon: Objects and Namespaces
  • March 28, Tues: PowerShell and the SQL Server Agent
  • March 29, Weds: Creating Agent Jobs
  • March 30, Thurs: Scheduling PowerShell Job Scripts
  • March 31, Fri: Auditing Permissions with PowerShell and Demos

If you couldn’t keep up, no worries – you can always purchase the course, or pick up my Recorded Class Season Pass Fundamentals to revisit the material when your schedule is less hectic. Hope you enjoy the free training!

View Details

Sometimes, y’all post questions at https://pollgab.com/room/brento and they don’t get a lot of upvotes, and reading through ’em, I bet it’s because other people don’t quite understand what you’re asking. I think there might actually be a good question at the heart of it, but … I’m just not sure what it is, and it needs to be rephrased.

Here’s a rundown of some of ’em that came in recently. If you recognize one of these as yours, you’re welcome to re-submit it at PollGab, but with clarification.


MonkeySQLDBA: Recently watched one of your video on fragmentation, great stuff. quick question, if your fill factor is set to 80, will the internal fragmentation get to 70% faster than leaving fill factor to 0?

Zoom out: what problem are you trying to solve? What’s the action that you would take based on this knowledge? Think about those, and then re-post the question.

Piotr: If SQL Server and PostgreSQL were aircraft which aircraft models would they be? F14 vs SU57?

I love the question, but I don’t know enough about aircraft to answer it. I don’t even know if those two airplanes are good, bad, or the same, hahaha.

Keith: Hey Brent! Is it safe to upgrade my Azure SQL database from compatibility level 140 to 160 just to be able to run the GENERATE_SERIES function?

Is it hard for you to create a numbers table? Like, really? I’m not being sarcastic, but if you need a list of numbers, why wouldn’t you just create one?

I Cannot Do This Alone: I’m sure it has always been hard to get skilled help, BUT… have you ever heard of “non-tech” companies sharing there tech talent in like a pool? I know I’m on the hook for a trashing here, but better by you than my CIO 😉

I think you’re describing outsourcing – having a group of full time tech employees that you can call on whenever you need them, and just pay for what you use.

“Can you show us your feet?” Wat?!?Henry: I am planning on an in place SQL Server upgrade from SQL Server 2012 to 2016 on a Windows Failover Cluster. All of my databases are in Full mode with Transaction logs taken every 5min. Should i put the databases in Simple during the upgrade?

Don’t upgrade in place, period.

Government Cheese: How do you like to measure IOPs for SQL Server storage (bare metal and cloud VM)?

First, I don’t, but even if I did – are you talking about measuring how many they already consume, or how much a new server provides? If you’re asking how many they already consume, how is that useful? You don’t know if the users are happy or not, or if you need to reduce storage throughput or increase it.

ConsultantWannabe: Hey Brent, you teach we should stand next to expensive things (like SS or Oracle) as contractors/consultants, any advice to identify our own expensive thing to stand next to? Obviously apart from standing nex to SS. Thanks

Are you … asking me … how to find out how much things cost? I’m confused. Why wouldn’t you just … ask management what the most expensive thing in the shop is?

Jeremiah Daigle: I have a server that has 2 8Core CPUs, and only have 8 enterprise core licenses. I was planning to just remove one of the CPUs, but ran into issues not having the blank to put back in. Is there anything to be concerned about by turning down each CPU to 4 cores in bios instead?

Having a blank to put in? I’m not sure what you mean – you shouldn’t need a “blank” CPU. I think someone’s pulling your leg, like they’re telling you to go get blinker fluid.

Maksimilian: What’s the best technique for a SQL sproc to self audit the params it was called with?

Self audit? Have the proc log them to a table. (I think I might be misunderstanding the question because it seems so obvious, but if you want to log something, and you’re in a database, well, uh, put it in a table.)

Eduardo: Linked-in provides automated public notification of completed course training. How should DBAs notify potential employers of completed Ozar training?

You mean … how do you add things to your resume in LinkedIn? I’m genuinely confused – are you asking how to edit your resume? I’m guessing you just click Edit on your profile, right? Put in whatever text you want there. If you’re saying that you have a problem because you need automation every time you complete any of my courses, and I have so doggone many of them, then stop putting each one – just put Fundamentals and Mastering.

Hangman: When is sp_whoisactive context_switches a useful metric for performance troubleshooting?

Ask whoever told you to look at that metric. Otherwise, don’t walk into the airplane cockpit, point at a gauge, and ask the pilot, “Hey, what’s that dial mean?” That’s not an effective use of anyone’s time. SQL Server is way worse than an airplane cockpit: there are precisely 1.21 gigawatts of metrics out there, and most of ’em just aren’t useful.

Eduardo: Is it good idea to start identity integer cols for new fast growing tables at the max negative value for a big int? Do you see this much in the field?

It’s fine. I almost never see it.

Tony: Will you be purchasing TSQL fundamentals 4th edition?

No. I’m sure it’s good, and I’m sure you doubt my T-SQL abilities, fair enough, but I’ve moved on to learning other stuff.

Isaac: How do you find all the queries that are using the kitchen sync query pattern (Col1 = @Col1Val or Col1 IS NULL) AND (Col2 = @Col2Val or Col2 IS NULL)? How do you find the worst of the worst?

Instead of looking for anti-patterns, ask, “What are the 10 worst-performing queries that I need to tune, and what are the anti-patterns in those?” That’s what sp_BlitzCache does.

TheCuriousOne: Hi Brent! From your perspective, is there any open problem/issue preventing a problem free upgrade from SQL Server 2019 to 2022 and if so, what are the gotchas to look out for?

Microsoft used to publish detailed upgrade guides for each version of SQL Server, but they stopped doing it. Check out the most recent one from 2014 (PDF) and that’ll give you a rough idea of how complex it is to migrate an existing environment.

Eduardo: What is your favorite graph database and why?

I don’t use any myself, so I’m not qualified to answer that.

Wasn’t_Me: We are thinking about switching from Azure to AWS. On docs.aws.amazon.com I find this phrase: “When you set up an Amazon RDS DB instance for Microsoft SQL Server, the software license is included.” What?? Does it means that on AWS I don’t have to pay SSRS, SSIS, SSAS?

Licensing is included in the hourly rate, yes. Amazon also offers bring-your-own-licensing. Keep in mind that you said RDS, and RDS doesn’t have SSRS, SSIS, and SSAS – you’ve got a lot more reading to do. Fortunately, I’ve got a training class to help.

Marian: Hi Brent! Have you even been to Romania? Would you consider attending some big tech event in Romania in the nearby future?

No, and since the pandemic, I’ve cut back a lot on my conference schedule. I’m sure Romania is nice, but I did a quick Google search and didn’t see any SQL Server conferences in Romania. I’m not really interested in non-SQL-Server conferences – when I want to learn other technologies, I tend to use cheaper/easier methods rather than traveling.

Neil: I set up all my SQL servers with TCP/IP enabled only. A developer is trying to connect with named pipes. Should I enable named pipes or force them to use TCP/IP?

I don’t have any opinion on this one whatsoever. (I don’t think I’ve ever disabled named pipes.) Why did you disable it?

View Details

Before heading out to Old Town for sightseeing, I went through your top-voted questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 00:44 Haydar: Is there a good way to suppress part of TSQL batch from showing the query plan in SSMS but having the rest of the batch show the query plan?
  • 02:13 Mike: Hi Brent, so simple blocking on a busy server, can cause a failover ? Is it because of exhaustion of thread workers, resulting in THREADPOOL waits? But I can’t understand the mechanism, how this can lead to failover – could you please explain ?
  • 03:03 Greef Karga: Please describe the most strict / locked down environment you have worked in and the challenges it posed.
  • 06:11 Q-Ent: Hi Brent. Have you ever used buffer pool extension as an option for better performance?
  • 07:29 Hangman: When is sp_whoisactive context_switches a useful metric for performance troubleshooting?
  • 08:36 AFriendOfMineAsk: Howdy Sir! Our CTO wants a monthly dashboard of all Production SQL Servers, can you please give some advice or any tips on what KPIs should include or should i have to start looking for a new job? Thanks and have a great day Sir!
  • 09:57 Jester: What tool do you like to use to find the worst performing queries with implicit conversions?
  • 10:55 Yaakov: What is the best way to print the line number currently executing inside a TSQL Sproc? 11:45 AM, no I’m not a morning person.: using where X in (1,2,3,4,5, etc) for selecting random sets of items. Is there any performance reason not to do this and instead use parameters or put them into a temp table first? Is it right to assume this won’t be able to be a cached query?
  • 12:59 Mike: Since 2005, new version of SQL Server had been released every 2, maximum 3 years. What is your opinion on when the next version (after 2022) will come out ? Will it be late 2024, sometime in 2025, or later, and why ?

View Details

You’re over the hump! Just two weeks left to go.

All month long, I’m giving away our newest class, Fundamentals of PowerShell for DBAs. Here’s what you’ll be learning this week:

  • March 20, Mon: Parameters and Error Handling and Demos
  • March 21, Tues: The SQL Server Module and Demos
  • March 22, Weds: The SQLSERVER:\ Drive
  • March 23, Thurs: Working With SQLSERVER Objects
  • March 24, Fri: Scripting Objects and Demos

In case you didn’t know before now, go head over to the class and watching the Before the Class modules that explain how to set up your workstation to follow along. Download these resources files to help, (The slide decks are also available to paid students.)

Not patient? Can’t wait for the rest of the videos to go live? Recorded Class Season Pass Fundamentals holders can jump in now – it’s included with your existing membership. Enjoy!

View Details

When In-Memory OLTP came out, I worked with it briefly, and I remember coming away thinking, “Who in their right mind would actually use this?” I was so horrified that I wrote a presentation about it and gave it at a couple of conferences:

Many laughs were had, but obviously that didn’t make me any friends at Microsoft, ha ha, ho ho. I figured I was done with Hekaton, and I wouldn’t ever have to see it again because y’all all saw the video, and you’d never be crazy enough to implement that feature.

Well, here it is in 2023, and recently I’ve talked to a couple of architects who wish they could go back in time and watch that video. In both cases, they suffered from the same issue.

The short story is that the more data you put into durable In-Memory OLTP tables – and even just 5GB of data can hit this issue – the more your startups, failovers, and restores turn into long stories, to the point where other databases on your SQL Server are practically unusable.

Setting up the 5GB Votes tableTo demonstrate the problem, we’ll start with a large copy of the Stack Overflow database. I’ll drop my nonclustered indexes just to make the next screenshot more clear, and then I’ll list the tables in the database to find a good candidate for the demo.

The highlighted table, dbo.Votes, has about 150 million rows and takes up about 5GB of space. That’s not big data by any means, and we can easily fit it in memory on our 8-core, 60GB RAM server. Let’s migrate it into In-Memory OLTP in order to make performance go faster:

ALTER DATABASE StackOverflow SET COMPATIBILITY\_LEVEL = 130, /* Or you can go higher, too */ MEMORY\_OPTIMIZED\_ELEVATE\_TO\_SNAPSHOT = ON;GOALTER DATABASE StackOverflow ADD FILEGROUP StackOverflow\_ram\_fg CONTAINS MEMORY\_OPTIMIZED\_DATA;GOALTER DATABASE StackOverflow ADD FILE (name='StackOverflow\_ram', filename='Z:\MSSQL\DATA\StackOverflow\_ram') TO FILEGROUP StackOverflow\_ram\_fg;GOSET ANSI\_NULLS ONGOSET QUOTED\_IDENTIFIER ONGOCREATE TABLE [dbo].[Votes\_InMemory\_1]([Id] [int] NOT NULL PRIMARY KEY NONCLUSTERED,[PostId] [int] NOT NULL,[UserId] [int] NULL,[BountyAmount] [int] NULL,[VoteTypeId] [int] NOT NULL,[CreationDate] [datetime] NOT NULL)WITH (MEMORY\_OPTIMIZED = ON, DURABILITY = SCHEMA\_AND\_DATA);GO/* Takes about 11 minutes on my machine: */INSERT INTO [dbo].[Votes\_InMemory\_1](Id, PostId, UserId, BountyAmount, VoteTypeId, CreationDate)SELECT Id, PostId, UserId, BountyAmount, VoteTypeId, CreationDateFROM dbo.Votes;GO After migrating that 5GB table to In-Memory OLTP, it’s taking up 5GB RAM, right? Well, no:

Try 28GB RAM. That’s why we have a sp_Blitz check to warn about high memory usage for In-Memory OLTP:

As to why an uncompressed 5GB rowstore table takes up 28GB RAM, that’s a topic for another blog post. (Sometimes, I imagine rowstore tables being introduced today – people would think they’re the most amazing thing ever.)

What happens when SQL Server restarts?For most of us, when we restart SQL Server, our biggest concerns are things like dropping connections, losing performance metrics, and starting over again with a fresh buffer pool. In-Memory OLTP users have a bigger problem: when the SQL Server restarts, CPU goes straight to 100%, and stays there:

Ouch. Why is CPU so high? Because with In-Memory OLTP, SQL Server starts up the database by reading the In-Memory OLTP tables up into something we call “memory.” It’s using less memory than before, thank goodness – it’s “only” 13GB – but 13GB of data still takes a long time to pull from disk and reconstruct in memory. (I’m not going to go into technical terms like crash recovery phases here because it’s not necessary to convey the overall problem.)

You can see exactly how long it takes in the SQL Server logs. In this case, the StackOverflow database recovery took 50 seconds – and in this case, because our server’s got really fast storage, the storage was able to deliver data so quickly that it pegged CPU at 100% for all 50 seconds.

During startup, wait stats show a lot of wait times on XTP_PREEMPTIVE_TASK and SLEEP_DB_STARTUP:

There’s also blocking, which is kinda funny – anything that needs to query sys.databases gets blocked, like IntelliSense queries running in the background:

This happens during failovers, restores, and attaches, too.Startups, failover clustered instance failovers, and restores all exhibit the same problem: they need to start up the database, and doing that means reconstructing the In-Memory OLTP data from scratch.

This is particularly problematic for shops that use Always On Availability Groups. Say you want to add a new database into an existing cluster, and the new database happens to use In-Memory OLTP. You restore it on the primary, and … boom, the server hits 100% CPU usage for an extended period of time, which affected all the running queries on existing databases on that server.

Here’s what CPU looks like at the end of a database restore:

CPU was relatively low while the restore was processing, but once SQL Server was done writing the files, CPU went straight to 100%. Why? Because it needed to bring the database online, which meant reading the In-Memory OLTP data from disk and reconstructing the table.

Even if you just attach an In-Memory OLTP database – a process that is normally near-instantaneous – you bring SQL Server to its knees while it reads through that data and populates memory.

In my example, I don’t have indexes on the In-Memory OLTP table, but if I did, the situation would be even worse. Indexes on these tables are only kept in memory, not on disk, so they’re reconstructed from scratch at startup, failover, restore, and attach time.

Bottom line: the more In-Memory OLTP durable data you have,
and the more databases you have that use it,
the worse this gets.

Trace flags 3408 and 3459 don’t help on SQL Server 2022, at least.Among other sources, Konstantin Taranov’s excellent trace flag list reports that trace flag 3408 forces all databases to use just one thread when starting up. I don’t think I’ve ever needed to use that trace flag, but it doesn’t appear to help here. In my lab, I set up 3408 in the startup config, restarted the SQL Server, and CPU still went straight to 100%:

Furthermore, 3408 doesn’t appear to have the desired effect on SQL Server 2022 (and I didn’t bother checking on other versions, since it wouldn’t have helped my client, as they had a lot of databases with In-Memory OLTP.) Databases are still starting up with multiple threads, which would drive CPU to 100%:

Same problem with trace flag 3459, which is supposed to disable parallel redo for AGs, but that’s unrelated to database startup, as we can see by the flames:

And just because someone’s going to ask, no, setting MAXDOP to 1 has no effect on system processes like bringing databases online.

So how do we get faster startups, failovers, and restores?In theory, you could add CPUs. In practice, that’s a really expensive way to solve this problem, and it doesn’t work when you have several (or heaven forbid, dozens) of databases that use In-Memory OLTP. SQL Server doesn’t just start up one database at a time – it starts them in groups, which means you can saturate lots of CPUs on restart. If you need to dive into the internals of this, here are a couple of resources:

  • Which databases are started up first, and how recovery is parallelized
  • Availability Group secondary redo and performance, then How many worker threads are used by Availability Groups – these are relevant because if you have a lot of databases using In-Memory OLTP, and if you chose In-Memory OLTP to reduce latch contention due to high concurrency writes, then you’re probably going to have to worry about parallel redo on the secondaries

In theory, you could use slower storage. Bear with me for a second: if your primary concern was that other databases on the SQL Server were unusable while In-Memory OLTP databases came online, you could actually put the In-Memory OLTP filegroup on slower storage. In this 5GB Votes table example, that does actually lower CPU usage during most of the process, only driving it to 100% near the end of the process:

(Yes, I actually tested that for one particular client, who was curious.) However, that also makes the In-Memory OLTP databases take even longer to come online! In my example with a 5GB table, the database took ~80 seconds to come online instead of ~50 – making your RTO goals tougher to meet.

In practice, minimize what you keep in In-Memory OLTP durable tables. A few ways to do that:

  • Make them schema-only instead, and don’t keep the data around. Yes, you lose all data when the SQL Server goes down, but if you’ve been using this feature for temporary data anyway, like session state, reconsider whether you need to keep it.
  • Sweep older data out to conventional tables. One of Microsoft’s design patterns for this feature is to use In-Memory OLTP tables only for ingestion, but then after the data’s been absorbed into the database, archive it.
  • Use regular tables instead, not In-Memory OLTP. Conventional tables don’t interrupt startup.

View Details

I’m on a boat! I’m on a 10-day Panama Canal cruise, and I stopped (well, not the boat) off the coast of Florida to answer questions y’all posted at https://pollgab.com/room/brento.

  • 00:00 Start
  • 00:56 DBe: In several places I’ve worked, it’s been “policy” to automatically restart heavy-use SQL servers off-hours on a regular cadence. Usually monthly but in a couple cases weekly. Is the scheduled restarting of SQL servers a common, viable business practice?
  • 03:53 BBDD: Hey Brent, do you know why a heap with one nvarchar100 column and 1row can be with size 2 GB and all used.What might have happened to the poor table. I tried to reproduce it creating the same table with inserting, deleting truncating but the size when it was back to 1 row was 1mb
  • 04:52 Brandon: Changing order of joins made a BIG difference for me recently, I suppose b/c it helped SQL start in a better place on the search for a good plan before time ran out. This was on 2008. Have you run into this much & do you think it’s less of an issue after 2008?
  • 06:04 Gigiwig: Hi Brent, a friend of mine has a server instance with a sql_… collation. One of the dbs is from a vendor and insists on a different collation. Can that cause problems concerning joining to system tables, using tempdb? How did you handle collation mismatches in the past? Thx
  • 07:43 Pamela Anderson: Has the problem introduced by PSPO implementation in SQL Server 2022 CTP – impossibility to tell which statement relates to which batch (or SP?), that you blogged about last year – been actually fixed in 2022 when it came out ? Or we have monitoring broken ?
  • 08:35 Runyan Millworthy: What are the top signs that a shop needs more SQL DBA’s?
  • 11:22 Kajimial: Hugs Brent, watched your video for optimizing checkdb? Isn’t with physical_only supposed to be faster? I ran it on 8TB db and completed for a little bit over a day and just checkdb completes for 6h? How can this be possible? DB with no load and running it with maxdop 0 with Ola
  • 13:27 Craig Gardner: I’m doing a penetration test on a server and have come across a SQL Server. Build number is 12.0.937.0 and version is 2014 (although I doubt this). I can’t find any information on that build number. Do Microsoft have a list of build numbers for Azure Managed Instances?

View Details

We’re almost halfway through the month. How’s it coming? You keeping up?

Or are you having a tough time because your work schedule is so busy and you can’t make 30 minutes of free time?

Hey, maybe that’s because you’re a production DBA who’s … trying to do too much work manually. See what I’m getting at? Make the time, bucko – it’s free. All month long, I’m giving away modules in our newest class, Fundamentals of PowerShell for DBAs.

Here’s what you’ll be learning this week, and only these videos are free each day:

  • March 13, Mon: Logical Operators and Loops and Demos
  • March 14, Tues: Filtering with WHERE
  • March 15, Weds: WHILE Loops and Demos
  • March 16, Thurs: IF-THEN-ELSE
  • March 17, Fri: Functions and Parameters and Demos

In case you didn’t know before now, go head over to the class and watching the Before the Class modules that explain how to set up your workstation to follow along. Download these resources files to help, (The slide decks are also available to paid students.)

Not patient? Need to revisit earlier modules, do the labs, or jump ahead? Recorded Class Season Pass Fundamentals holders can jump in now – it’s included with your existing membership. Enjoy!

View Details

Is your company hiring for a database position as of March 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here.

If your company is hiring, leave a comment. The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

I’m coming back to Boston for SQLSaturday this October 14th!

On Friday the 13th (muhaha), before the event, I’m teaching a one-day pre-conference workshop on Mastering Query Tuning.

You need to speed up a SQL Server app, and you’re allowed to change the queries and indexes – but not the server hardware or settings. Good news – I’ll teach you how in a day of learning and fun. Join me, Brent Ozar, as I explain how to make your SQL Server apps go faster.

We’ll cover:

  • How SQL Server builds query plans
  • How to choose between CTEs, temp tables, and APPLY
  • How to tune for SELECT * and lots of rows
  • How to write dynamic SQL that scales
  • How to avoid pitfalls like deadlocks and bad batching

Save $50 on early bird registration now. The class will be held at the Microsoft Technology Center at 5 Wayside Road, Burlington MA 01803. Seating is limited to 114 folks. I will be there in person, and it will not be recorded or broadcast online.

Other helpful links:

  • Register for the SQL Saturday event with lots of other sessions – that’s the Saturday event, keep in mind, not my workshop
  • Read more about the event – with the location, volunteering, and more
  • Speakers can submit sessions now

View Details

You’re a production database administrator responsible for the health, security, and uptime of many database servers.

You’ve been pointing and clicking your way through SSMS for years, scripting out T-SQL to files, but… when you need to do the same task repeatedly across several servers, it’s a bit of a pain.

You’ve told yourself someday you’d learn PowerShell to do repeatable, reliable automation.

That time is now, and it’s free!

All March long, I’m giving away our newest class, Fundamentals of PowerShell for DBAs. Block out a half-hour per weekday on your calendar now because on each weekday in March, a different video will be live – but just for one day only! You gotta keep up if you wanna learn for free. (I’ll be making the videos public manually, so it won’t be at an exact time – just rest assured that if you log in at the same time every day, you’ll always have a fresh video to watch. If you log in at different times each day, well … you might not. Sorry about that.)

Here’s what you’ll be learning this week:

  • March 6, Mon: CMDLETs: Aliasing and the Pipeline and Demos
  • March 7, Tues: Working with Objects and Demos
  • March 8, Weds: Object Properties and the Pipeline and Demos
  • March 9, Thurs: Object Methods
  • March 10, Fri: Making Your Own Objects

In case you didn’t know before now, go head over to the class and watching the Before the Class modules that explain how to set up your workstation to follow along. Download these resources files to help, (The slide decks are also available to paid students.)

Not patient? Can’t wait for the rest of the videos to go live? Recorded Class Season Pass Fundamentals holders can jump in now – it’s included with your existing membership. Enjoy!

View Details

Back in 2020 before the wheels came off the world, I’d scheduled visits to Gothenburg and Oslo for their annual SQL Server events. Now that things are back to normal, it’s back on!

Data Saturday Gothenburg, Aug 26 & 28, 2023 – Monday Post-Con: Mastering Server Tuning – You’re constantly facing new performance challenges on different servers. You need to quickly diagnose a server’s bottleneck, and learn the most common ways to fix each bottleneck. Let’s tackle it together in a fast-paced 1-day version of my full 3-day class, and because we can’t cover everything, attendees get a year’s access to the full 3-day recorded class too. Learn more and register for the workshop now.

Data Saturday Oslo, Sept 1-2, 2023: Friday Pre-Con: Mastering Query Tuning – You need to speed up an existing app, and you’re allowed to change both queries & indexes, but you can’t throw hardware at it. Let’s tackle it together in a fast-paced 1-day version of my full 3-day class, and because we can’t cover everything, attendees get a year’s access to the full 3-day recorded class too. Learn more and register for the workshop now.

View Details

The clock starts now!

You’re a production database administrator responsible for the health, security, and uptime of many database servers.

You’ve been pointing and clicking your way through SSMS for years, scripting out T-SQL to files, but… when you need to do the same task repeatedly across several servers, it’s a bit of a pain.

You’ve told yourself someday you’d learn PowerShell to do repeatable, reliable automation.

All month long, I’m giving away our newest class, Fundamentals of PowerShell for DBAs. On each weekday in March, a different video will be live – but just for one day only! You gotta keep up if you wanna learn for free. (I’ll be making the videos public manually, so it won’t be at an exact time – just rest assured that if you log in at the same time every day, you’ll always have a fresh video to watch. If you log in at different times each day, well … you might not. Sorry about that.)

Here’s what you’ll be learning this week:

  • March 1, Weds: What’s PowerShell?
  • March 2, Thurs: Using Variables
  • March 3, Fri: Using CMDLETs and the Pipeline and Demos

In case you didn’t know before now, go head over to the class and watching the Before the Class modules that explain how to set up your workstation to follow along. Download these resources files to help, (The slide decks are also available to paid students.)

Not patient? Can’t wait for the rest of the videos to go live? Recorded Class Season Pass Fundamentals holders can jump in now – it’s included with your existing membership. Enjoy!

View Details

To find out, let’s set up a simple status log table:

DROP TABLE IF EXISTS dbo.StatusLog;CREATE TABLE dbo.StatusLog (TimeItHappened DATETIME2 PRIMARY KEY CLUSTERED, Step VARCHAR(20));GO And then let’s try a two-part transaction:

BEGIN TRAN INSERT INTO dbo.StatusLog VALUES (GETDATE(), 'Step 1'); WAITFOR DELAY '00:00:01'; BEGIN TRAN INSERT INTO dbo.StatusLog VALUES (GETDATE(), 'Step 2'); SELECT @@TRANCOUNT AS OpenTransactions; Right now, SQL Server shows that I have 2 open transactions:

What Happens If I Roll Back?But what does “2 open transactions” mean, really? If I do a rollback, what gets rolled back? Let’s find out:

ROLLBACK;SELECT @@TRANCOUNT AS OpenTransactions;SELECT * FROM dbo.StatusLog; The results:

Both of our transactions were rolled back, and there’s nothing left in the table.

Let’s Try It Again, but Commit This TimeRoll through the same setup code, but then commit:

BEGIN TRAN INSERT INTO dbo.StatusLog VALUES (GETDATE(), 'Step 1'); WAITFOR DELAY '00:00:01'; BEGIN TRAN INSERT INTO dbo.StatusLog VALUES (GETDATE(), 'Step 2');GOCOMMITSELECT @@TRANCOUNT AS OpenTransactions;SELECT * FROM dbo.StatusLog; The results are a little weird:

Only one transaction is shown as open – and right now, both rows are in the results table. If we roll back now, what happens?

Even though we said we “committed” our inner transaction, it doesn’t matter – BOTH of our transactions got rolled back.

You Can’t Really Nest Transactions Like This.Think of @@TRANCOUNT as the number of times remaining that you either need to commit or roll back. If you open a bunch of nested transactions in a row, it’s up to you to commit every single one of ’em. If ANY of them are rolled back, EVERYTHING is rolled back.

This is particularly troublesome if you try to break up locking by using a bunch of little transactions wrapped in one big outer transaction. I recently had a client who thought they could:

  1. Start an outer transaction for a business process
  2. Start an inner transaction, acquire locks on OrderHeader, make changes, commit, and release the OrderHeader locks when the transaction committed
  3. Go on to another inner transaction, acquiring other locks on OrderDetails, while other processes were able to work lock-free on the OrderHeader table because step 2’s locks were released

But as you can see here, even when you commit one part of a transaction, SQL Server still isn’t quite done with it. It has to maintain those locks because if any of your open transactions are rolled back, SQL Server’s gonna roll back everything you did – even the parts you thought were finished.

Update: a couple of commenters have pointed out SAVE TRANSACTION, and I gotta say I’m not a fan of that because of the complexity, especially around lock escalation. If you choose to use that feature, read the documentation really carefully, especially around lock escalation. Saved transactions don’t release the locks once they’ve been escalated, and if you’ve been through my Mastering classes, you know how easy it is to hit lock escalation.

View Details

Aaron Bertrand posted a challenge:

We’re going to use the AdventureWorks sample database (get your copy here), where the folks in marketing requested a list of users to e-mail a new promotional campaign. The customers need to meet at least one of the following criteria:

  • last placed an order more than a year ago
  • placed 3 or more orders in the past year
  • have ordered from a specific category in the past two weeks

These criteria don’t have to make sense! They just need to make the query a little bit more complex than your average CRUD operations.

First, we’re going to update Sales.SalesOrderHeader to modern times so that dates make sense relative to today. We only care about OrderDate here, but there are check constraints that protect a couple of other columns (as well as a trigger that sometimes fails on db<>fiddle but that I have no energy to troubleshoot):

DISABLE TRIGGER Sales.uSalesOrderHeader ON Sales.SalesOrderHeader;GO DECLARE @months int; SELECT @months = DATEDIFF(MONTH, MAX(OrderDate), GETDATE()) FROM Sales.SalesOrderHeader; UPDATE Sales.SalesOrderHeader SET DueDate = DATEADD(MONTH, @months-1, DueDate);UPDATE Sales.SalesOrderHeader SET ShipDate = DATEADD(MONTH, @months-1, ShipDate);UPDATE Sales.SalesOrderHeader SET OrderDate = DATEADD(MONTH, @months-1, OrderDate);GO ENABLE TRIGGER Sales.uSalesOrderHeader ON Sales.SalesOrderHeader;

This stored procedure that someone wrote will now return data (without the update, it would be hard to write predictable queries based on, say, some offset from GETDATE()).

create proc sp\_find\_customers(@paramIntCategoryId INT)asselect customerid, firstname, emailaddress from( -- last placed an order more than a year ago select distinct customerid, firstname, emailaddress from sales.customer a (nolock), person.person b(nolock), person.emailaddress c(nolock) where personid = b.businessentityid and b.businessentityid = c.businessentityid and (select max(orderdate) from sales.salesorderheader (nolock) where customerid = a.customerid) < dateadd(yyyy,-1,convert(DATE,getdate())) union -- placed at least 3 orders in the past year select distinct customerid, firstname, emailaddress from person.person p (nolock) join person.emailaddress e (nolock) on p.businessentityid = e.businessentityid join sales.customer c (nolock) on personid = p.businessentityid where customerid in (select customerid from sales.salesorderheader (nolock) where orderdate between dateadd(yy, -1, convert(DATE,getdate())) and getdate() group by customerid having count(*) >= 3) union -- ordered within specified category in past two weeks select distinct customerid, firstname, emailaddress from person.emailaddress em (nolock) join person.person pp with (nolock) on em.businessentityid=pp.businessentityid join sales.customer cu (nolock) on personid = pp.businessentityid where customerid in (select top (2147483647) customerid from sales.salesorderheader oh (nolock) join sales.salesorderdetail od (nolock) on oh.salesorderid = od.salesorderid and datediff(day, oh.orderdate, convert(DATE,getdate())) <= 14 join production.product pr (nolock) on od.productid = pr.productid inner join production.productsubcategory AS sc (nolock) on pr.productsubcategoryid = sc.productsubcategoryid and sc.productcategoryid = @paramIntCategoryId order by customerid)) x order by 1 Now, it’s your turn: how many bad practices can you find in that code?Aaron’s answers are over here. I’ve turned off comments on this blog post because if you have any questions or thoughts, you should post ’em on Aaron’s blog post. The only reason I’m posting this here is that I bet a lot of y’all aren’t subscribed to Simple Talk, and I wanted to break this challenge up into two parts – the code to review, and the answers. Do not look at the answers until you’re done with your code review. Have fun!

View Details

Not all of the questions y’all post at https://pollgab.com/room/brento require long-winded responses.

Brandon: Do you seen a rise in json queries to address impedance mismatch between data/objects? I struggled with EF to produce a query that was neither simple nor complicated against a properly designed db (according to 2 experts). Dropped EF; used json query in stored proc; it was magic.

No.

Rufus: What are the best ways to determine if two large query plans have the same shape?

Put them side by side in SSMS and zoom out.

Stan Redman: What is your opinion of the SQL force encryption setting?

I don’t do security or compliance work, so I have no opinion.

Dance Monkey: Do you think there would be much interest for someone to host a PostgreSQL office hours on Youtube/Twitch?

Yes.

Eduardo: What is highest number of DBs you could safely put in an always on availability group?

Read this.

Marian: Hi Brent! Would you recommend any SQL Server Certification that would be easily recognizable? I know Microsoft retired those on SQL Server, and focus on Azure.

No.

Hondo: What is the top batch requests per second (sustained) that you have seen in the field? What were the specs for the underlying hardware to support that kind of load?

At the moment, 150K sustained, 4 socket, 64 core box with 256GB RAM. Small data set, just lots of tiny well-tuned queries that can’t effectively be cached client side.

Rooster: How do you determine the the optimal Virtual Memory page file size for bare metal Windows Server 2019 running SQL Server 2019 Enterprise?

Read this.

Sigríður: Is there anything we can do to to influence the stat sampler so that a given index key (customer in this case) is included as one of the histogram 200 steps? We know who the top 200 most important customers are by $$$$.

Yes, filtered statistics. They’re just like filtered indexes – put a where clause on ’em.

Tim: Greetings Brent. Are you winging it? Or do you sneak a peek at pollgab before starting the stream, so that you’re prepared? If you are winging it, how long did it take until you were confident in your knowledge and no longer had to prepare?

This one takes a little longer to answer, but I’m putting it in this batch because it’s fun.

Before starting the show, I look at the PollGab queue to remove anything that might be offensive or isn’t a good fit for my show (like if someone asks a MySQL question.) In the process of looking at ’em, I at least see what’s coming. I don’t ever go Google for stuff – either I know the answer, or I’m going to tell people what I’d Google, but that’s it.

How long did it take? Well, Office Hours is a really good simulation of what it’s like to be a consultant. Client staff constantly throw questions at you, and you have to be really comfortable either saying you know the answer, or saying you don’t, but you know where you would look. You can’t feel guilty about saying you don’t know. So I’ve been really comfortable with what I do know for a long time – but it’s just that the scope of that surface area slowly and steadily grew over time.

I still make mistakes! In a recent show, I said I didn’t think unique constraints also created a unique index under the hood. One of the viewers pointed out the mistake. Strangely, I get excited about that because it means I still have stuff to learn!

View Details

Thanks to this technique to run SQL Server on Apple Silicon chips, I’m now developing exclusively on my Mac! I’ve been using a Mac for over 15 years, but in the past, I’ve always used Windows at some layer somewhere. This time around, it’s all Mac the whole way down, which is kinda nifty. Makes my release process easier.

Wanna watch me use it? Take the class.To get the new version:

  • Download the updated FirstResponderKit.zip
  • Azure Data Studio users with the First Responder Kit extension:
    ctrl/command+shift+p, First Responder Kit: Import.
  • PowerShell users: run Install-DbaFirstResponderKit from dbatools
  • Get The Consultant Toolkit to quickly export the First Responder Kit results into an easy-to-share spreadsheet

Consultant Toolkit ChangesI updated it to this month’s First Responder Kit, but no changes to querymanifest.json or the spreadsheet. If you’ve customized those, no changes are necessary this month: just copy your spreadsheet and querymanifest.json into the new release’s folder.

sp_BlitzCache Changes* Enhancement: when using @SortOrder = ‘all’, there’s a new pattern column to show which metrics sucked about the query, and it’s included in the table output. (#3172, thanks Adrian Buckman.) * Fix: case sensitivity issues on joining to sys.all_columns. (#3233, thanks sm8680.)

sp_BlitzFirst Changes* Fix: QRY_PROFILE_LIST_MUTEX lock timeouts on sys.dm_exec_query_statistics_xml. (#3210, thanks sqlslinger.)

sp_BlitzLock Changes* Fix: error converting data type nvarchar to bigint. (#3201, thanks Erik Darling.) * Fix: arithmetic overflow in wait_time_hms when wait time added up to more than 2147483647. (#3215, thanks Vlad Drumea.) * Fix: string or binary data would be truncated in table tempdb.dbo.#deadlock_owner_waiter. (#3206, thanks johnkurtdk.)

sp_BlitzWho Changes* Fix: shows procedure definition even if the current statement isn’t in the plan cache. (#3163, thanks Adrian Buckman.) * Fix: tempdb allocations did not include internal objects such as worktables and workfiles. (#3174, thanks Adrian Buckman.)

For SupportWhen you have questions about how the tools work, talk with the community in the #FirstResponderKit Slack channel. Be patient: it’s staffed by volunteers with day jobs. If it’s your first time in the community Slack, get started here.

When you find a bug or want something changed, read the contributing.md file.

When you have a question about what the scripts found, first make sure you read the “More Details” URL for any warning you find. We put a lot of work into documentation, and we wouldn’t want someone to yell at you to go read the fine manual. After that, when you’ve still got questions about how something works in SQL Server, post a question at DBA.StackExchange.com and the community (that includes me!) will help. Include exact errors and any applicable screenshots, your SQL Server version number (including the build #), and the version of the tool you’re working with.

View Details

Today’s episode of Office Hours is brought to you by Quest Software. I went through your top-voted questions from PollGab.com/room/brento, and, uh, kinda looked like I was sponsored by Fendi while doing it, hahaha:

Wow, those logos are bigger than I thought. Here’s what we covered:

  • 00:00 Start
  • 01:20 reluctantly_tolerant : I used FCI instead of AG for server w/500 DBs due to worker thread limit. I used NetApp ONTAP filesystem and was very impressed by performance, and ability to spin up clone of production in under 2min. Now I feel this is the gold standard. Why go back to AGs, even where possible?
  • 02:42 Simon: First off: I know we should not use the NOLOCK hint :] But can NOLOCK queries even cause index corruption on queries that is NOT modifying data? Perhaps if combined with persisted computed columns? (SQL Server 2019, latest CU).
  • 03:58 LogarTheBarbarian: Hello hello Brent! What questions come to mind if you came upon MSSQL instances that modified the Ola DBCC CheckDB job to run CHECKTABLE, CHECKALLOC, and CHECKCATALOG on different days rather than CheckDB in its entirety?
  • 05:15 Dru: When should a unique constraint be used vs a unique index?
  • 06:32 Sigríður: What are your favorite things about living in San Diego and Las Vegas?
  • 08:38 Sigríður: What is your favorite standing desk and why? What are the specs?
  • 09:18 Peter Seale: VAGUE question: we found that 80% of our db data is used by indexes. Is this normal-ish? Any vague tips for reducing our data usage? Most tips focus on data used by tables, and never mention data used by indexes.
  • 09:56 Piotr: What are your thoughts on upgrading from SSRS2014 where we have numerous reports? Best to migrate to SSRS2019 or skip entirely and starting learning how to migrate to PowerBI server? Currently on-prem but planning on moving to Azure.
  • 12:54 Maksim: What do you use for motivation to read tech docs and tech books?
  • 14:05 PartyPerson: Hey Brent, what is the story behind the “California deserves whatever it gets” sign behind you?
  • 15:20 TeeJay: A lot of our reports are computationally expensive and run repeatedly for each subscription. I assume that the solution to this is to pre-aggregate the DW data as much as possible, but suspect that I’m probably re-inventing the wheel. (Budget: £0) What words should I be googling?
  • 16:34 Alex: Hi Guru, I have some small tables on Azure SQL DB with very little use. Once in a while a scheduler runs a SP that performs one insert to a table in 2 concurrent threads. I have a gap in identity column. I added TABLOCKX as suggested by docs but problem still arises.
  • 18:08 depthcharge: Hi Brent, have you ever encountered a scenario where you indexed to remove an eager index spool, and SQL Server ignores the index and continues spooling? Aside from index hints (which help, but we can’t change the code), any other clubs I can hit the optimizer with?
  • 19:13 toepoke.co.uk ;-): Hey Brent, In a recent office hours you spoke of encrypting data on the app side rather than the db side which I found interesting. How would this work from a sorting perspective, eg sort a UI table by Last name,First name, etc. Store the first letter ? Store the hash? Cheers!
  • 20:51 Q-Ent: Hi brent, are you aware of MCR(Maximum consumption Rate ) for CPU sizing? Do you think this is a reliable method ?
  • 22:01 Wren: Hi Brent! Building some reports for our SQL Server environments and I found one of your old (2009) replies on Stack about finding CPU time per database… do you think it’s a worthwhile stat to use to determine “what should move to cloud first”? Any improvements since SQL2008?
  • 23:23 Tim.: Hi Brent. I like the fundamentals of powershell. Will there be a mastering powershell? Will you be working with Drew more in the future?
  • 24:50 Stone Temple Pilot: How do you measure bad page splits for inserts on a poor clustered index?
  • 25:17 Paco: Hello Brent, I have a friend who is facing a server that has both threadpool waits and Non-Yielding Schedulers occurring around the same time, until they cause the AG to fail. Have you seen threadpool waits cause Non-Yielding Schedulers or vice versa?

View Details

Y’all post and upvote questions at https://pollgab.com/room/brento, and I stream sessions on my Twitch.tv channel where I answer ’em and chat with the audience.

  • 00:00 Start
  • 02:09 Chad Baldwin: Hey Brent! “a friend told me” MSSQL will use an index’s stats to generate a plan, but not use the index itself.
  • 03:25 Jeremiah Daigle: Hey Brent, I’ve been unable to proceed past Compat mode 140… with recurring battles with “8657 – Could not get the memory grant” Is there a new configuration option?
  • 04:48 PatchesOHoulihan: Oh wise and benevolent Oz(ar), has there been any chatter around the DCOM hardening patches Microsoft started releasing last July, and the final March patch?
  • 05:20 Haydar: What is your opinion of the new optimized locking functionality in Azure SQL DB?
  • 06:43 CompletedFundamentalsAndMastering: sp_blitzIndex shows 3 minutes of lock waits on CX after just 2 days uptime (large, over-indexed table). 1 NCX shows 24s lock waits, but all others are 0, including one with 19 cols!
  • 07:39 Geoff Langdon: Hi Brent, When using AGs with a read only replica, there doesn’t seem to be a way to map a new user to the read only replica database on the replica
  • 08:47 Alex: Hi Brent, I’m conducting interviews for potential candidates in SQL. Currently I’m exposing Azure SQL DB to public IP so that candidates can connect from home to take a test.
  • 09:45 Peter: Hello Brent. To get a steady Plan Cache we set PARAMIZATION = FORCED on several DB’s. After tuning the most resource intensive queries, would you then recommend to go back to SIMPLE?
  • 10:53 Leif: A friend told me that an unused index can reduce performance of a select statement. Is that possible ?
  • 12:01 Boris: Ahoi! Is finnaly the time to migrate my old ETL SSIS packages to Azure Data Factory?
  • 13:56 thevibrantdba: My friend is a novice and is wondering if there are any known links to see at glance what SQL server version brought what feature for prospective interviews.
  • 16:11 Andrew P.: Hi Brent, my three person data team about to merge into a much larger team as part of a merger (an SME merging into an enterprise).
  • 18:14 Patricia Zysk: Using SSIS, SSRS, Agent jobs in daily on-prem work, do you recommend SQL Server in a VM or Azure SQL Managed Instance when moving to the cloud
  • 19:28 MI: Hi Brent, Sooo… how many queries have you had chatgpt optimize yet?
  • 19:40 Rando: Hi Brent! How does one confidently decide on a dump/backup interval for databases.. n times a day, etc.. What’s reasonable
  • 20:34 Clippy 2.0: Do you think ADS will become the better tool for query performance tuning in the long run?
  • 21:46 One_of_the_Party_People: Hi Brent. I work with a highly normalized database with nearly 2k tables. Some of the FK’d data will cascade 10+ levels deep. Is there a resource you can point me to for how to go about archiving data?
  • 23:01 LarrySQL: Hi Brent, I have a proprietary database where all stored procedures are encrypted (WITH ENCRYPTION) and some are slow. I can’t see execution plans in SSMS. I wonder if SQL SERVER can do optimization on this kind of encrypted objects.
  • 23:59 George : Do not upvote:
  • 24:31 Chris: Is there a good argument for continuing to take backups of read only databases, or do you take one last backup, validate it and test restore it then never worry about backups again?
  • 25:29 neil: sp_who shows like 1000 sleeping connections. sp_whoisactive just shows like 20 or 30 queries. sometimes Windows Events throws an error about being unable to reuse a spid. do i need to address this ?
  • 26:24 Q-Ent: Hi brent, Do you have any plans for discount offers other than black Friday for your classes ?
  • 26:43 Jeremiah Daigle: Have you run across scenarios where you had to turn MEMORY_GRANT_FEEDBACK_PERCENTILE_GRANT = OFF, in order to get around Memory Grant Errors related to Exceeding max config limits
  • 27:15 Champaign DBA: Do you have a blog post about the limitations of Azure features such as automatic index turning compared to the power of the sp_blitz tools?
  • 28:23 alwayslogshipping: From your experience, what is the notable missing link between skill set and the personality shops want to entrust with delivery of business values.
  • 30:13 BrentFan: Hi Brent, If you were tasked to take over SQL code deployment in production from the development team. How would you approach this?
  • 31:51 Maksim Bondarenko: What is the best (with mininum downtime) way to migrate databases between two different 2 node AlwaysOn Clusters (4 different servers)? SQL Server 2016 Enterprise to SQL Server 2019 Enterprise. One AG,few dbs and around 2 TBs of data. Also AG name must be the same after migration
  • 32:27 Nicolas: Hi Brent, a friend of mine wants to move a large column (a few KB) of an existing table to a second separate table to “optimize the logical reads on the Cluster index of the first table when the large column isn’t used”.
  • 33:17 Mr. SqlSeeks: I am researching Always Encrypted, trying to get around the cross-database query limitation. Are you aware of any way to use the same key in multiple databases?

View Details

It’s Valentine’s day – let’s do some matchmaking!

Is your company hiring for a database position as of February 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment.

The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

While waiting for the dry cleaner to open, I went live to stream a quiet session going through a bunch of y’all’s questions from https://pollgab.com/room/brento.

Here’s what we covered:

  • 00:00 Start
  • 01:45 Rollback is single threaded: Hi Brent! In microservices application architecture, Using a database per service or a shared database? I asked this because using a database per service is not straightforward and there are many drawbacks. Thanks!
  • 03:39 fajitapete: Covering indexes, what benefit is derived once you are past 2-3 columns, wouldn’t putting the rest as included be just as good
  • 05:07 ILoveData: SQL 2022 makes it easier to call external endpoints. In your eyes as a DBA, what acceptable use cases (if any) are there for a feature like this? I appreciate the idea, but we all know how this ends up once devs find out it exists…
  • 07:02 Dopinder: What is your opinion of SSMS 19? Anything to get excited about?
  • 07:52 Sajan: Do you have any interesting arguments to explain why you shouldn’t use Managament Studio on an instance with a SQL server? My argument was mainly that the price of the license is conditioned by the amount of CPU (which is wasted by unnecessary applications)
  • 08:47 Mike: My on-prem server has 16 physical cores / 32 logical cores. If we migrate this box to SQL Server on Azure VM, how many vCPUs we need – 16, or 32 ?
  • 09:54 Mike: When you deploy Azure VM with preinstalled SQL Server 2019 EE, it only shows projected VM cost. What will be the additional (hidden) SQL license cost $ per core / month? Is it $274 as in new billing model in SQL 2022 (selected during SQL install), or different amount ?
  • 11:04 DevInHiding: Hi Brent, an older colleague of mine claims that (at least in much older versions of SQL Server) that it is better to query bit data type fields as “WHERE fieldname anything other than 0” than “WHERE fieldname = 1”. Is there anything to that?
  • 12:06 Curious DBA: In what scenarios would you utilize CROSS APPLY instead of INNER JOIN? Is CROSS APPLY an optimal way to get SQL Server to do several backward seeks (1 per row) instead of a large forward seek? (I.E. composite PK (ID, DateTime) and want to return max(DateTime) for multiple IDs)
  • 13:14 zlobnyfar: WhatIsTheBestWayOfLogsGeneratingAbout CRUD interactions (changes in roles or permission) AND AUTHENTICATIONS (login attempts (success/failures) and attempts to elevate privileges (success/failures)) AND executed QUERIES stats AND SA Actions Thanks for comprehensive answer!
  • 15:32 Dont Bother Answering: Hey Brent, why does my query go parallel when it’s cost in sp_BlitzCache (33.7) is lower than cost threshold for parallelism (35)? Just looking to understand why, thank you!
  • 16:40 Trushit: What do you think will be the impact of tools like ChatGPT on SQL developers? Which role do you think will be most impacted : developer, development DBA or production DBA? What skills will remain relevant even when AI learns low level coding?
  • 18:09 BlackFriday-Bundle2: Hi Brent and thanks for the courses. What is your view on PAGE vs ROW compression in SQL Server? Would you consider it a bad fit for multi part NC where latter key parts and included columns are “hot”? Finally, does it ever make sense to change FILLFACTOR if compression is on?
  • 18:57 Fillfactor 1% for the win: Hi Brent, what are your thougths about creating 3 docker container on a physical box, one for dev, one for test and one for live. It’s for a (modern and classic) DWH environment. Live is using all resources during night, and during the day the developers can work on dev/test.
  • 20:22 YouGottaDoWhatYouGottaDo: Hi Brent, what’s your opinion on the new T-SQL snapshot backup functionality in SQL Server 2022? Do you see any hidden problem to be aware of?
  • 21:18 Brandon: Any insights to offer regarding how db design might differ (or if it should) when developing for microservices, and any resources or people to follow for further study? For example, do you find it common to have many DBs where traditionally there would only be one or two?
  • 22:48 RufusStone: Asking for a friend, what is a suitable punishment for someone who creates a database with space in its name?
  • 23:44 i_use_uppercase_for_SELECT: How do you manage expectations at your clients that not all index changes won’t have unexpected consequences? Create and index that helps several queries, but causes another to blow up because of a new query plan.
  • 25:26 Sajawal: Hi Brent, You are doing great for people like me who love to play with SQL. Would you please let us guide what is DOP feedback architecture in SQL Server 2022?

View Details

You’re a production database administrator responsible for the health, security, and uptime of many database servers.

You’ve been pointing and clicking your way through SSMS for years, scripting out T-SQL to files, but… when you need to do the same task repeatedly across several servers, it’s a bit of a pain.

You’ve told yourself someday you’d learn PowerShell to do repeatable, reliable automation.

That time is March, and it’s gonna be free!

All March long, I’m giving away our newest class, Fundamentals of PowerShell for DBAs. Block out a half-hour per weekday on your calendar now because on each weekday in March, a different video will be live – but just for one day only! You gotta keep up if you wanna learn for free. (I’ll be making the videos public manually, so it won’t be at an exact time – just rest assured that if you log in at the same time every day, you’ll always have a fresh video to watch. If you log in at different times each day, well … you might not. Sorry about that.)

Here’s what you’ll be learning:

  • March 1, Weds: What’s PowerShell?
  • March 2, Thurs: Using Variables
  • March 3, Fri: Using CMDLETs and the Pipeline and Demos
  • March 6, Mon: CMDLETs: Aliasing and the Pipeline and Demos
  • March 7, Tues: Working with Objects and Demos
  • March 8, Weds: Object Properties and the Pipeline and Demos
  • March 9, Thurs: Object Methods
  • March 10, Fri: Making Your Own Objects
  • March 13, Mon: Logical Operators and Loops and Demos
  • March 14, Tues: Filtering with WHERE
  • March 15, Weds: WHILE Loops and Demos
  • March 16, Thurs: IF-THEN-ELSE
  • March 17, Fri: Functions and Parameters and Demos
  • March 20, Mon: Parameters and Error Handling and Demos
  • March 21, Tues: The SQL Server Module and Demos
  • March 22, Weds: The SQLSERVER:\ Drive
  • March 23, Thurs: Working With SQLSERVER Objects
  • March 24, Fri: Scripting Objects and Demos
  • March 27, Mon: Objects and Namespaces
  • March 28, Tues: PowerShell and the SQL Server Agent
  • March 29, Weds: Creating Agent Jobs
  • March 30, Thurs: Scheduling PowerShell Job Scripts
  • March 31, Fri: Auditing Permissions with PowerShell and Demos

Get started now by heading over to the class and watching the Before the Class modules that explain how to set up your workstation to follow along. Download these resources files to help, (The slide decks are also available to paid students.)

Not patient? Wanna get started on it right away? Recorded Class Season Pass Fundamentals holders can jump in now – it’s included with your existing membership. Go get your learn on!

View Details

We went up to Michigan to see my dad’s side of the family, and the snow came down just in time for our arrival. Always love the fresh snow look.

So I stood outside and took your top-voted questions from https://pollgab.com/room/brento. Let’s see what y’all came up with today:

Here’s what we covered:

  • 00:00 Start
  • 00:27 York!: Hi Brent! Recently you indicated in your Weekly Links that you aren’t a fan of schemas in a db. Can you elaborate as to why? Thanks!
  • 02:06 Brian: Linked servers; you bash them and yes they’re evil and slow. You’ve said “why not connect directly to the server that has the data”, I agree. But in cases where my friend has data on two servers (can’t consolidate them) and you need to query it together, how do you optimize that?
  • 03:52 Youssef L.: Hi Brent, I’ve been a paid SQL DBA since I was 17(5 years ago), I landed a Senior position and I’m one of 2 DBAs in the company working on a huge migration project from on-prem to Azure(600DBs). Management wants to use MI while I want always on approach.what do you think is best?
  • 04:50 M.: Hi Mr. Brent. Can you tell me why it is bad for performance to write WHERE datecolumn = getdate()? Thank You.
  • 05:36 Dru: Is the Pluralsight business model not long for this world since content creators can make so much more $$$ hosting their own training videos?
  • 05:51 Dance Monkey: Is it ok to simultaneously install Windows updates and SQL cumulative updates at the same time via windows update?
  • 06:49 Frank Drebin: What is the next version of SQL Server that will be deprecated in the first responder kit? When will this take place?
  • 07:46 Peter Riis: Hello Brent. Querying Spatial Data are sometimes really slow. The est. vs. act. number of rows using spatial functions can be way off. I joined your Level 2 Bundle and can’t find any hints on tuning these Queries. Do you have any ideas on tuning Queries on Spatial data?
  • 09:08 Patricia Zysk: Considering the limitations of both, what SQL feature do you recommend for tracking changes AND knowing which user made the change/date. In 2023 seems silly to have to write a trigger for part 2 of this with CDC. Thanks!
  • 10:07 thevibrantdba: In a prior webcast you mentioned Andy leonard for SSIS and my experience with the videos has been amazing. Now, who is the brent ozar for SSRS?
  • 10:49 Lenny: What is your opinion of distributed partitioned views in SQL Server?
  • 11:31 ConsultingMadness: While discussing reporting requirements, a client explained an internal process that sounded like a backdoor to avoid a tax requirement. It sounded a little sketchy. Have you ever encountered something like this, did you keep working with them, or have other advice to share?

View Details

Lots of good questions on today’s broadcast! If you’d like to submit one, go to https://pollgab.com/room/brento and upvote the ones you’d like to see me cover.

Here’s what we covered today:

  • 00:00 Start
  • 01:05 Testing123: When inserting or updating data into a table, from a concurrency perspective, does it make sense to break up the complicated SELECT logic into a staging table and then bulk load/update the data into the destination. i.e. Will SQL only grab exclusive locks at the end of the tran?
  • 03:00 Curious DBA: Hi Brent. What query tuning approach would you take to force SQL Server to do multiple backward seeks instead of one expensive forward seek? I.E. Composite PK on (ID, Datetime). Search for max(datetime) on a single ID does a backwards seek, multiple IDs do 1 expensive fwd seek.
  • 05:11 Dru: What are the pros / cons of setting the SQL Server vm clock to UTC time instead of local time?
  • 06:08 George : Is it OK that when you give a caustic answer I call you “Brentward” in a slightly disapproving tone? (As if it’s your full name) P.S. I’ve gotten a new job with help from your classes. Definitely going to get the full set.
  • 07:55 DianaCarneiro: Hi Brent, I’m currently using an AlwaysOn AG configuration with WFCLs, and it has a few instances running on 2017. I was wondering if I can upgrade just one instance from 2017 to 2019 while keeping the rest on 2017. What do you think? The info about it is nothing concrete.
  • 09:43 Sid: What is the advantage of using sys.partitions over doing a count() over a table to get the count? We seem to be having some locking issues since sys.partitions is the same table as opposed to count() being separated. maybe a nolock hint?
  • 11:20 Mike: When you deploy Azure SQL Server VM (preinstalled SQL 2019), it only shows VM cost. For Ent. Edition – what will be the additional (hidden) license cost per CPU core ? Is it $274/month, same as in new 2022’s Pay-As-You-Go license billing model, or it is different amount ?
  • 12:08 Stone Tablet Monk: What is the best data warehouse design book for SQL Server?
  • 13:43 depthcharge: Hi Brent, took your Fundamentals of TempDB course and used it to diagnose and correct GAM page contention in TempDB, thanks! Is the guidance for correcting GAM waits the same for user databases? All my googling just turns up articles on TempDB.
  • 15:00 Elad: I have a table with identity column as clustered PK with high fragmentation. only inserts and updates without any deletes. updates is datetime2, decimal and int columns, no string datatype Table size ~500K rows with ~25K updates and ~10K inserts in 24hr. What can be the cuase? 15:54 Stone Tablet Monk: What are your favorite PostgreSQL books?
  • 18:09 GucciRules: Hi Brent, in Azure SQL Managed Instance, backups are automated; however, it doesn’t appear that the system databases are included in these automated backups. Any idea if they are in some form, or whether we need to run our own sysdb backups?
  • 19:10 Steve: We have a consultant who disabled CPU0 because he had a box with 128 cores and CPU0 was experiencing huge contention with VMWare activity. This server has 8 cores, so disabling a core is a big impact on performance. Should I ask to enable the core, or does he have a point?
  • 21:18 Porsh-uhh: I remember hearing vaguely about issues with SQL Server 2022 pre-release which negatively impacted monitoring tools in some way. Are there any issues like that with the release of 2022 and do they affect the First Responder Kit? Anything to really worry about deploying 2022?
  • 22:14 Dru: Is SSMS query plan viewing better with one large monitor or multiple smaller monitors? What is optimal monitor size for this?
  • 23:24 Phineas: What are your thoughts about manually clearing SQL wait stats? When should this be done?
  • 24:12 The Fall Guy: How do you decide when to store data as JSON blobs vs storing data in a well defined schema?
  • 25:15 Tugay Ersoy (Admiralkheir): Hi Ozar, We have enabled CDC in SQL Server 2016 to catch the changes. After a while, the log file got too big and we couldn’t shrink it.When CDC is open, it pulls SQL Log status to REPLICATION and does not allow us to process,so we had to close CDC How can we implement a solution
  • 26:25 Dance Monkey: Is it reasonable to update stats with full scan for a single table NC index as the first job step before running the next job step that does work on a very large DW Fact table?
  • 29:15 Kevin: Asking for a friend: is the order of records guaranteed when inserting them in a transaction? The app sends row1 and row2 with their own CreationDate (set in the app) but in SS, row2 has an earlier date. Is this expected behavior? If not, any starting points?
  • 30:37 ShiftHappens: HI Brent, in my job 99% of the time I do not need to do any kind of sql tuning, however there are times when there comes these really complicated procs whose perf is bad and I try my best to tune but I am not the best at it. Any advice on how I can get better at it?

View Details

Before heading out to dinner, I went through your highly-upvoted questions from https://pollgab.com/room/brento.

Here’s what we covered in this episode:

  • 00:00 Start
  • 00:20 Mert: Hi Brent, what is the relation between AlwaysOn and Windows Failover Cluster? Is WFC an obligation or a choice for creating an Always On availability group? It will be nice if you address the topic with shapes visually. Thanks.
  • 01:12 LemonOnAPear: Whats your favorite SQL Server bug / story about a bug?
  • 02:26 franklwambo: Have you plans to ship the current or future SQL server training classes to pluralsight? my company seems more inclined to the plural sight subscriptions.
  • 03:04 Call Me Ishmael: Enforcing referential integrity via foreign keys is often a source of friction between application developers and the database team primarily because of the discipline that entails and perceived performance issues. There are blogs that offer alternatives. What is your opinion?
  • 04:14 don s: Have taken your Fundamentals of Columnstore course more than once, great course! My question is for Azure Synapse Analytics and the Columnstore implementation in this environment. Same old Columnstore or has Microsoft made any improvements to the deterioration issues?
  • 05:11 TiredAndFrustrated: We have a lot of ad hoc queries in the plan cache (over 33%). In your opinion, which is better, Optimize of Ad Hoc or Forced Parameterization. Devs won’t change the code….
  • 06:03 flynders: Why do perfmon counters show lower figures for IO latency compared with sys.dm_virtual_io_file_stats ? I see much higher latency figures from the DMV using Paul Randals IO time period script. I would expect the values to be close, not maybe 5x off using identical capture interval
  • 07:41 Philip: What do you typically recommend/like/see “comment” wise when it comes to documenting within your Stored Procedures, Functions, etc ?

View Details

In a recent Office Hours post, David Reabow suggested letting ChatGPT answer a few of the questions y’all posted at http://pollgab.com/room/brento/. Brilliant! Let’s see how it does. I purposely cherry-picked the questions that I thought ChatGPT would have the easiest time answering.

Rollback is single threaded asks: Hi Brent! An update statement has blocked all other sessions. What should I do? Killing it, restarting SQL server service, waiting, etc. What’s your opinion? Thanks!

ChatGPT answered:

If an update statement has blocked all other sessions, there are a few options to consider:

  1. Monitor the situation: If the update is taking a long time, monitor it to see if it’s making progress. If the update is hung, it may eventually clear up on its own.
  2. Kill the blocking query: If the update is not making progress, you can use the KILL command to stop the blocking query. This will allow other sessions to proceed, but any data changes made by the blocked update will be rolled back.
  3. Restart the SQL Server service: Restarting the SQL Server service can clear up any blocked sessions, but this should be done as a last resort because it will cause an interruption to all other sessions.
  4. Wait: In some cases, waiting is the best option. If the update is expected to run for a long time, and there are no pressing issues with other sessions being blocked, waiting may be the best course of action.

In any case, it is advisable to take a backup of the database before taking any action to avoid data loss.

Brent says: bullet points 1 and 4 are basically the same. I abhor bullet point 3 because it doesn’t add anything that bullet point 2 wouldn’t have done. It was on the right track – bullet points 1 and 2 are good starting points.


Peter Riis: Hello Brent. We got a database storing mainly images in BLOB. Storing BLOB’s in the database got several disadvantages, so we thought about implementing FILESTREAM. What are your opinion on storing files in a database?

ChatGPT says:

Storing large files like images in a database can have the following disadvantages:

  1. Increased database size: Storing large files in a database can significantly increase its size, making it slower to manage and query.
  2. Slower performance: Querying and retrieving large files from a database can be slower than accessing them from a file system.
  3. Limited scalability: Storing large files in a database can limit scalability as the database grows in size and complexity.

On the other hand, FILESTREAM is an option that allows you to store large binary data (BLOBs) in a database, while maintaining the efficient streaming access to that data. FILESTREAM integrates the SQL Server database engine with the NTFS file system to store and manage large BLOB data.

In conclusion, whether to store large files in a database or not depends on the specific requirements and use cases of the application. If efficient streaming access to the large files is required, FILESTREAM can be a good option. However, if the focus is on performance, scalability, and managing large files efficiently, storing the files outside the database in the file system might be a better solution.

Brent says: nailed it.


Stone Tablet Monk: When creating a new index, what is your opinion of using OPTIMIZE_FOR_SEQUENTIAL_KEY for minimizing last page insert contention? Is this a good solution? Is this the only solution?

ChatGPT says:

The OPTIMIZE_FOR_SEQUENTIAL_KEY option can be used when creating a new index to minimize last page insert contention, by prioritizing index page allocation for new data rows at the end of the index. This can help reduce index fragmentation and improve insert performance.

However, this is not the only solution to minimize last page insert contention. Other solutions include:

  1. Increasing the fill factor: The fill factor determines the percentage of space that is reserved on each index page for future growth, and increasing it can reduce the frequency of index page splits.
  2. Using a clustered index: A clustered index physically orders the rows of a table, so new rows are added to the end of the table.
  3. Monitoring and defragmenting indexes: Regular monitoring and defragmentation of indexes can help maintain their efficiency and reduce the frequency of page splits.

In conclusion, using OPTIMIZE_FOR_SEQUENTIAL_KEY is a valid solution for minimizing last page insert contention, but it should be evaluated along with other options to determine the best approach for a specific scenario.

Brent says: ChatGPT is simply flat out wrong here. Fill factor is a setting that isn’t honored during inserts. Clustered indexes are irrelevant here, too. This answer illustrates one of the challenges with AI – it can’t synthesize information on brand new terms and topics where there isn’t already conventional wisdom for it to analyze. Now, for the answer: what I’d ask is, how do you know that you have last page insert contention? This typically shows up at over 1,000 inserts per second, sustained – and most people I see asking this question, don’t even have the problem.


Piotr: When are SSMS client statistics helpful in troubleshooting query performance issues?

ChatGPT says:

SQL Server Management Studio (SSMS) client statistics can be helpful in troubleshooting query performance issues in the following situations:

  1. Long-running queries: If a query is taking a long time to complete, client statistics can provide information on the execution time, wait time, and other details about the query.
  2. Slow network performance: If a query is running slow due to network latency, client statistics can show the time spent sending and receiving data between the client and the server.
  3. High CPU or memory usage: Client statistics can help identify queries that are consuming high amounts of CPU or memory on the server, allowing you to focus your performance optimization efforts on the most resource-intensive queries.
  4. Blocked queries: If a query is blocked by another query, client statistics can provide information about the blocking and blocked sessions, which can help in identifying the root cause of the problem.

To enable client statistics in SSMS, right-click the query window and select “Include Client Statistics” in the context menu. After the query has completed, the client statistics will be displayed in the results pane.

Brent says: again, ChatGPT is just bullshitting here, and most of this is just flat out wrong. Client stats don’t show wait time or blocking queries. As to the real answer – for me, client statistics haven’t been useful.

Here’s the problem with ChatGPT.It speaks with the same level of authority no matter how much or little confidence it has in its answers. It never says “I think” or “I suspect” or “Perhaps” or “I don’t know.” It just confidently struts right onstage and speaks loudly.

I stopped after four questions because I think these 4 really sum up the problem with ChatGPT today.

If you have tech questions, ChatGPT could theoretically be useful if you already know the right answers, and you can weed out the garbage. But … if you already know the right answers, what’s the point?

I do think AI has tons of good uses, like writing real estate listing text, but answering database questions isn’t one of ’em.

View Details

ChatGPT, Resource Governor, manually created stats, Always Encrypted, and as always, fragmentation: let’s answer your questions from https://pollgab.com/room/brento.

Here’s what we covered today:

  • 00:00 Start
  • 01:13 Timbalero: Hi Brent. my friend knows your view on rebuilding indexes. He also thinks that external index fragmentation affects pretty much only readahead scans. For scientific purposes, what metrics should he look at to see if defrag makes a difference (if only marginal)?
  • 02:21 chandwich: Hey Brent! What kind of advantages (or disadvantages) do you anticipate with the recent emergence of ChatGPT, specifically in the SQL world. Have you used it?
  • 04:23 BrentsFastCars: Hi Brent, I have been reading one of your posts about running SQL Server in a virtual environment. You talk about when there are more cores than Standard allows and using affinity masking to disable cores. Have you seen your customers disable hyperthreading as another solution?
  • 05:40 Bill Bergen: Brent…I have to say it again….you are a genius….now to the question….is there a way to correctly and completely use TSQL to script out all parts of resource governor for migration to another server
  • 06:48 TomInYorks: Hi Brent. What arguments are there for and against manually creating statistics on every column of every table when auto create/update statistics options are enabled?
  • 09:15 Wasn’t_Me: A software company produce a software for compensations and bonuses. They cannot use their own software internally otherwise some employees could see the compensations of other employees. Can Always Encrypted be the solution and who should own the keys? The CEO?
  • 12:25 Life-long Learner: My friend asked me the other day while we were talking about archiving a 2TB Audit Table, to reduce its size and we asked what was better, rebuild the indexes or drop and recreate? Thank you very much for everything, I love your courses!!!

View Details

Wanna learn about SQL Server and the Microsoft data platform, but you don’t wanna sit through long videos?

Enjoy short videos on TikTok?

I’ve got just the thing: I’m taking the best Q&A from Office Hours and putting ’em out as individual videos. That way, as you’re swiping through practical jokes, friendship goals, candid idiocy, music reimaginations, and dog tips, you can also learn a little in bite-sized chunks, too.

@brentozarultd Do you have any resources/tips on a new dba needing to inventory the servers/instances/databases at a company? I have around 30 servers that I want to start documenting that currently have 0 physical documentation. Thanks Brent! #sqlserver #sql #dba #database #microsoft #hacks #tips #brentozar #azure

? original sound – Brent Ozar Unlimited

For those tech answers, follow @BrentOzarULTD on TikTok. Or, if you prefer stalking my personal life, my own account is @BrentOzar.

View Details

Y’all just never run out of interesting questions at https://pollgab.com/room/brento! I’m impressed, got another great round today.

Here’s what we covered:

  • 00:00 Start
  • 00:25 Chrisbell: Recently we’ve been facing thread starvation issues. How can we troubleshoot it when even sp_whoisactive ( even with DAC ) is unresponsive and takes forever to return a result set ? How can we get to the root cause of this since its all happening within a few seconds ?
  • 01:24 Lu: We disable TLS 1.0 and 1.1 on our windows servers; how to affect the SQL server and SSIS jobs?
  • 05:19 Macrieum: Hi Brent, I am at the beginning of my sql career and trying to set up select query across 50+ sites/servers that all share a vpn/domain. 4+ hours of work/week saved if the query returns to a central location. Can you point me in a starting direction? Thank you
  • 06:32 RoJo: What is best way to update/patch with least downtime? patching current box seems risky.
  • 07:41 Don’tBotherAsking: Hey Brent. Love your work. We have a database in which all PII (names, birthdates, etc) is column-level encrypted. Query performance is getting worse over time–presumably because it has to decrypt more and more data. Is there any way to optimise queries on encrypted columns?
  • 09:25 Kalfr: What are the best options for oopsy query recovery in SQL 2019 Enterprise AG shops?
  • 11:28 pete: How important are non-equality columns in indexes after all they might follow 2-4+equality columns
  • 12:42 Safraz: Hey Brent. From your weekly links, I discovered that EVE ONLINE used SQL Server 2005 at one point and they documented their issues with scaling hardware to improve performance. I’m not sure if this is still the case but have you ever consulted for them?
  • 13:30 Piotr: What are the top causes for SQL log shipping breakages?
  • 14:17 Robbaco: Could 2 Create Index statements in the same DB and same schema lock each other (no FK relations) because of inserts/updates/deletes on the sys-tables? could data for unrelated objects change in the sys-tables (something like a reorg)?
  • 15:26 PhilRich: I have an automated process (weekly) that restores backups (Full/Diff/Logs) to a test server – runs DBCC – and then reports on all the databases. Is there any point in running DBCC on the production servers?
  • 18:22 Dru: What’s the best monitoring software for vanilla PostgreSQL, Aurora PostgreSQL, and Azure PostgreSQL?
  • 19:08 Mike: Sorry if this has been asked before, but – if you were to explain to your boss who does not understand who Database Administrator is – and what he does – how would you do it ?
  • 20:35 Kevin: What’s your least favorite part of being a consultant? what advice would you give to someone who wants to follow your footsteps? Thanks

View Details

Twenty years ago this month (next Wednesday to be exact), sysadmins and database administrators started noticing extremely high network traffic related to problems with their SQL Servers.

The SQL Slammer worm was infecting Microsoft SQL Servers.

Microsoft had known about it and patched the problem 6 months earlier, but people just weren’t patching SQL Server. There was a widespread mentality that only service packs were necessary, not individual hotfixes.

The problem was made worse because back then, many servers were directly exposed to the Internet, publicly accessible with a minimum amount of protection. Since all the worm needed was access to port 1434 on a running SQL Server, and many folks had their servers exposed without a firewall, it spread like wildfire.

Even if only one of your corporate SQL Servers was hooked up to the Internet, you were still screwed. When that server got infected, it likely had access to the rest of your network, so it could spread the infection internally.

So what have we learned in 20 years?In terms of network security, a lot. I don’t have raw numbers, but it feels like many, many more client servers are behind firewalls these days. But… like with the original infection, all it takes is just one SQL Server at your shop to be infected, and if that one can talk to the rest of the servers in your network, you’re still screwed if something like Slammer strikes again.

In terms of patching SQL Server, to be honest, I don’t think we’ve learned very much. Most of the SQL Servers running SQL ConstantCare still aren’t patched with the latest Cumulative Updates, and many of them are several years behind in patching.

We’re just hoping that the worst bugs have been found, and no new security bugs are getting introduced.

Hope is not a strategy. Patching is. Patch ’em if you’ve got ’em.

View Details

After I stopped selling live classes, I took some time off all live broadcasting period. It was a nice couple of months over the holidays, had a good time with the family, and now I’m starting to fire up my Twitch channel again.

I’m not setting a schedule yet, just broadcasting when I have time available, so if you want to get alerted when I start streaming, subscribe to that channel and turn on notifications.

Here are the questions we discussed:

  • 00:00 Start
  • 06:17 JimLic: In moving to new physical servers with virtual disks which are claimed to be ‘better’ than our old physical disks, replicas are showing super slow redo queues. What is the importance of block size across replicas? Anything we configuration with SQL and/or disk? Any Tests?
  • 08:20 Chris Stoll: Do you have any resources/tips on a new dba needing to inventory the servers/instances/databases at a company? I have around 30 servers that I want to start documenting that currently have 0 physical documentation. Thanks Brent!
  • 09:54 Mike: I’ve never used a Mac nor Azure Data Studio. Will Mac and ADS be enough to perform my DBA duties, or should I restrain to Windows and SSMS due to ADS missing something important?
  • 10:55 TK_Bruin: Yo Brent! What would you say are the top 2 or 3 functions or features that SQL Server has added over the last 5 years that have been the most transformative or promising in terms of business benefits?
  • 13:18 Ted Striker: Any tips or gotchas when tuning queries that use OpenQuery to run a remote OleDB SQL query?
  • 14:21 Roger Murdock: What are the best/ worst filegroup design strategies you see in the wild?
  • 15:48 chandwich: Hey Brent. I just completed your Fundamentals of and Mastering classes, but I haven’t applied it all directly to my job yet. How would you recommend I show this off on my resume?
  • 17:00 Dru: When default invocation of sp_whoisactive takes 3.5 minutes to produce a resultset, what is the first thing you would look for in those results?
  • 17:38 Nick12: Hi Brent. How’s your week? Is there a way to avoid an eager spool for the halloween problem in a simple UPDATE query that sets a column to a fixed non-null value and filters for that column being null?
  • 20:56 Wren: Would you recommend using a surrogate key similar to a row-id (autoincrement integer) even if there is a usable unique PK column in a table?

View Details

To follow along, you’ll need:

  • An Apple Mac with an Apple Silicon processor (M1, M2, etc – not an Intel or AMD CPU)
  • Azure Data Studio
  • Docker Desktop 4.16.1 or newer
  • An Internet connection

In Docker Desktop, go into Settings, Features in Development, and check the box for “Use Rosetta.” That’s the new 4.16 feature that allows you to run Intel-focused apps like Microsoft SQL Server on Apple Silicon.

  1. Download & Run the SQL Server ContainerWe’ll follow the instructions from Microsoft’s documentation, but I’m going to abbreviate ’em here to keep ’em simple. Open Terminal and get the latest SQL Server 2022 container. You can run the below command in any folder – the file isn’t copied into your current folder.

sudo docker pull mcr.microsoft.com/mssql/server:2022-latest That’ll download the ~500MB container, which takes a minute or two depending on your Internet connection. Next, start the container:

sudo docker run -e "ACCEPT\_EULA=Y" -e "MSSQL\_SA\_PASSWORD=<YourStrong@Passw0rd>" \ -p 1433:1433 --name sql1 --hostname sql1 \ -d \ mcr.microsoft.com/mssql/server:2022-latest Don’t use an exclamation point in your password – that can cause problems with the rest of the script. (Frankly, to keep things simple, I would just stick with upper & lower case letters plus numbers.)

In the above example, the container’s name will be sql1. If you decide to get fancy and change that, remember the name – you’ll need it later.

You’ll get an error about the platform – that’s okay, ignore it. Docker Desktop will show the container as running:

And in less than a minute, you can connect to it from Azure Data Studio. Open ADS and start a new connection:

  • Server name: localhost
  • Port: 1433
  • Username: sa
  • Password: the one you picked above

With any luck, you’ll get a connection and be able to start running queries. To have fun, we’re going to want a sample database.

  1. Download & Restore the Stack Overflow DatabaseAgain, I’m going to abbreviate and change Microsoft’s documentation to keep things simple. Open Terminal and go into a folder where you’d like to keep the backup files. In my user folder, I have a folder called LocalOnly where I keep stuff that doesn’t need to be backed up, and I have Time Machine set to exclude that folder from my backups.

cd ~/LocalOnly If you don’t have a folder like that, you can just go into your Downloads folder:

cd ~/Downloads Download the Stack Overflow Mini database, a small ~1GB version stored on Github:

curl -L -o StackOverflowMini.bak 'https://github.com/BrentOzarULTD/Stack-Overflow-Database/releases/download/20230114/StackOverflowMini.bak' Make a backups folder inside your Docker container – note that if you changed the container name from sql1 to something else in the earlier steps, you’ll need to change it here as well:

sudo docker exec -it sql1 mkdir /var/opt/mssql/backup Copy the backup file into your container:

sudo docker cp StackOverflowMini.bak sql1:/var/opt/mssql/backup In Azure Data Studio, restore the database:

RESTORE DATABASE StackOverflowMini FROM DISK='/var/opt/mssql/backup/StackOverflowMini.bak'WITH MOVE 'StackOverflowMini' TO '/var/opt/mssql/data/StackOverflowMini.mdf', MOVE 'StackOverflowMini\_log' TO '/var/opt/mssql/data/StackOverflowMini\_log.ldf'; Presto – you now have the Stack Overflow database locally.

  1. Stop & Start the Docker ContainerWhen you want to stop it, go to a Terminal prompt and type:

docker stop sql1 Because you’re exceedingly smart and almost sober, you can probably guess the matching command:

docker start sql1 And yes, the database will still be there after you stop & start it.

For Mac Users, This is a Godsend.Because this just works, at least well enough to deal with development, blogging, demoing, presenting, etc. For those of us who’ve switched over to Apple Silicon processors, this is fantastic. I love that I can work on the First Responder Kit without having to fire up a Windows VM.

This isn’t for production use, obviously, and it’s not supported in any official way. In this post, I didn’t touch on security, firewalls, SQL Agent, other versions of SQL Server, performance tuning, memory management, or anything like that, nor do I intend to get involved with any of that in Docker anyway.

This particular combination of technologies (plain Docker running SQL Server for Linux on a Mac with Apple Silicon processors) is brand spankin’ new as of last week, so there isn’t anything out on the web in the way of troubleshooting. However, if you want to learn more about the two components that are probably the most new to you (Docker and SQL Server for Linux), subscribe to Anthony Nocentino of Nocentino.com. He’s the go-to person for SQL Server on containers & Linux. He’s got several Pluralsight courses on these, too.

View Details

I am waaaay overdue for a haircut, but instead of being a responsible adult, I stopped to take your questions from https://pollgab.com/room/brento.

  • 00:00 Start
  • 00:43 Mike: We have 3 Dell PowerEdge R630 servers with SQL Server installed. Everything functions for 3.5 years straight. How long is it expected to work?
  • 01:30 Shalom: What are the worst incidents that you have witnessed due to SQL errors being routed to a mail folder that nobody ever reviewed?
  • 02:40 TheBigMC: Hi Brent. I’m about to start a new job where I’ll be looking after 100 SQL Servers. I’ve been told that’s a guess. How can I reliably scan a network to find servers people don’t even know exist
  • 05:00 Steph: Hi Brent, what are your top most dangerous seemingly benign SSMS menu items for which you shouldn’t approach your mouse pointer when connected on a prod database (for instance I once misclicked on ‘Fragmentation’ in ‘index properties’ on a prod db…). Thanks.
  • 06:02 Tim: Hi Brent. With Windows Server 2022 you can set the allocation unit size of a disk up to 2M. Is 64k still the best practice for SQL Server?
  • 07:58 DGW in OKC: Do people actually use Identity columns any more? What are the pros and cons of this practice?
  • 08:26 IndexingForTheWin: Hi, the company I now work for has taken the decision since 3 years to completely stop index rebuilds and only do stats updates. Wouldn’t we benefit from rebuilds (perhaps yearly)?
  • 09:18 Hamish: What are the pros/cons of using TSQL PRINT for debugging sprocs vs using table variables for debugging sprocs?
  • 09:44 Max: A friend of mine ask, what is better – add a bit field and index it on VLTB (over 2 Tb in size) with 60+ fields and 13 indexes already OR create a new table to store PK values of rows which have value 1 for this new field? Thanks
  • 12:10 John Bevan: Q1. When you have SQL running on an AzureVM, is it acceptable to use the D drive (i.e. low latency but ephemeral) over an attached disk for the TempDB?

View Details

Normally, y’all post and upvote great questions at https://pollgab.com/room/brento, but in today’s episode, y’all upvoted some stinkers. Buckle up.

  • 00:00 Start
  • 00:47 SQLKB: Hi, according to sp_BlitzCache I usually have more than 260k plans in cache, created in the past 1 hour, is it a big number? Comparing number of plans from exec_query_stats vs exec_cached_plans the numbers are 260k vs 130k , what could cause the diff between those numbers?
  • 02:23 Chase C: What do the options under linked server provider settings mean? “Allow inprocess” is frustratingly un-googleable and my technical manuals for SQL Server are also rather short on content. Cheers!
  • 04:09 sELECT RAM: You mentioned that PLE is useless recently. Why? and what is the alternative?
  • 05:21 Call Me Ishmael: Will SQL Server ever mandate the semi-colon as a statement terminator?
  • 07:35 Mike: What do you think about running SQL Server in Kubernetes for Production workloads in year 2023?
  • 09:07 Yitzhak: You once used a nice analogy in relating pilots to air planes and DBA’s to SQL Servers. Will you please share that again?
  • 10:47 Haddaway: When moving large tables to a new file group, does it ever make sense to do the migration with bcp command line vs using TSQL to copy the data to new location via insert?

View Details

Writing new code = bugging. That part’s easy.

Taking those bugs back out, that’s the hard part.

Developers are used to their tools having built-in ways to show what line of code is running now, output the current content of variables, echo back progress messages, etc. For a while, SQL Server Management Studio also had a debugger, but it was taken out of SSMS v18 and newer versions. Even when it was around, though, I wasn’t a big fan: SQL Server would literally stop processing while it stepped through your query. This was disastrous if your query was holding out locks that stopped other peoples’ queries from moving forward – and you just know people were using it in production.

I do wish we had an easy, block-free way of doing T-SQL debugging in production, but T-SQL debugging is different than debugging C# code. So if your T-SQL code isn’t doing what you expect, here are a few better ways to debug it.

Option 1: Use PRINT statements.Since the dawn of time, developers have put in lines like this:

BEGIN TRANPRINT 'Starting access date changes'UPDATE dbo.UsersSET LastAccessDate = GETDATE()WHERE DisplayName = N'Brent Ozar';PRINT 'Done with access date, starting reputation changes'UPDATE dbo.UsersSET Reputation = Reputation / 0WHERE DisplayName = N'jorriss';PRINT 'Done with reputation changes'COMMIT So that when the statement fails, they can at least see which part failed:

There are a few problems with this approach:

  • PRINT doesn’t output data immediately. SQL Server caches the data that needs to be pushed out to the Messages. If you’re troubleshooting a long-running process, you probably want to see the messages show up immediately, as soon as they’re executed.
  • PRINT pushes data out over the network whether you want it or not, adding to the overhead of your commands. This isn’t a big deal for most shops, but when you start to exceed 1,000 queries per second, you’ll want to shave overhead where you can. You only really want the debugging messages coming out when you need ’em.

Let’s raise our game with RAISERROR.

Option 2: Use RAISERROR, pronounced raise-roar.What? You didn’t notice that it’s misspelled? Okay, confession time, I didn’t realize that either – Greg Low of SQLDownUnder pointed it out to me. Let’s add a little more complexity to our code:

DECLARE @Debug BIT = 1;BEGIN TRANIF @Debug = 1RAISERROR (N'Starting access date changes', 0, 1) WITH NOWAITUPDATE dbo.UsersSET LastAccessDate = GETDATE()WHERE DisplayName = N'Brent Ozar';IF @Debug = 1RAISERROR (N'Done with access date, starting reputation changes', 0, 1) WITH NOWAITUPDATE dbo.UsersSET Reputation = Reputation / 0WHERE DisplayName = N'jorriss';IF @Debug = 1RAISERROR (N'Done with reputation changes', 0, 1) WITH NOWAITCOMMIT I’ve added a @Debug parameter, and my status messages only print out when @Debug = 1. Now, in this example, I don’t really need a parameter – but in your real-world stored procedures and functions, you’re going to want one, and you’ll want the default value set to 0, like this:

CREATE OR ALTER PROC dbo.DoStuff @MyParam VARCHAR, @Debug BIT = 0 AS... That way, you only turn on the debug features manually when you need ’em, but the app doesn’t call @Debug, so it just gets left at its default value, 0.

I’ve also switched to RAISERROR instead of PRINT because RAISERROR has a handy “WITH NOWAIT” parameter that tells SQL Server to push out the status message to the client right freakin’ now rather than waiting for a buffer to fill up.

When you’re troubleshooting long or complex processes, you’re probably going to want to dynamically drive the status message. For example, say it’s a stored procedure that takes hours to run, and you wanna see which parts of it took the longest time to run. You’re not gonna sit there with a stopwatch, and you’re not gonna come back later hoping that the queries will still be in the plan cache. Instead, you wanna add the date/time to the RAISERROR message.

Unfortunately, RAISERROR doesn’t support string concatenation. Instead, you have to pass in a single string that has everything you want, like this:

DECLARE @Now NVARCHAR(50);SET @Now = CONVERT(NVARCHAR(50), GETDATE(), 26);RAISERROR (N'Done with reputation changes at %s', 0, 1, @Now) WITH NOWAIT Which gives you the date at the end of the output:

You can even pass multiple arguments in – check out the RAISERROR syntax for more details on how the arguments work.

Option 3: Use Table Variables.You’ve probably heard advice from me or others warning you that table variables lead to bad performance. That’s true in most cases – although sometimes they’re actually faster, as we discuss in the Fundamentals of TempDB class. However, table variables have a really cool behavior: they ignore transactions.

BEGIN TRANDECLARE @Progress TABLE (StatusDate DATETIME2, StatusMessage NVARCHAR(4000));INSERT INTO @Progress VALUES (GETDATE(), N'A one');INSERT INTO @Progress VALUES (GETDATE(), N'And a two');ROLLBACKSELECT * FROM @Progress ORDER BY StatusDate; So even though I did a rollback, not a commit, I still get the contents of the table variable:

This is useful when you’re:

  • Troubleshooting a long-running process
  • The process has try/catch, begin/commit type logic where something might fail or roll back
  • Desiring the results in tabular format, possibly even with multiple columns, XML, JSON, whatever

And there you have it – 3 ways to work through debugging without using the discontinued SSMS Debugger. I typically use RAISERROR myself – it’s easy enough to implement, and it’s a technique you’ll use forever. There are more ways, too, and you’re welcome to share your favorite way in the comments.

View Details

When someone says, “Find all the rows that have been deleted,” it’s a lot easier when the table has an Id/Identity column. Let’s take the Stack Overflow Users table:

It has Ids -1, 1, 2, 3, 4, 5 … but no 6 or 7. (Or 0.) If someone asks you to find all the Ids that got deleted or skipped, how do we do it?

Using GENERATE_SERIES with SQL Server 2022 & NewerThe new GENERATE_SERIES does what it says on the tin: generates a series of numbers. We can join from that series, to the Users table, and find all the series values that don’t have a matching row in Users:

DECLARE @FirstId INT, @LastId INT;SELECT @FirstId = MIN(Id),@LastId = MAX(Id)FROM dbo.Users;SELECT gs.valueFROM GENERATE\_SERIES(@FirstId, @LastId, 1) gsLEFT OUTER JOIN dbo.Users u ON gs.value = u.IdWHERE u.Id IS NULL; The LEFT OUTER JOIN seems a little counter-intuitive the first time you use it, but works like a champ:

What’s that, you ask? Why does GENERATE_SERIES have fuzzy underlines? Well, SQL Server Management Studio hasn’t been updated with the T-SQL syntax that came out in the last release.

Thankfully, Microsoft separated the setup apps for SSMS and the SQL Server engine itself for this exact reason – the slow release times of SSMS were holding back the engine team from shipping more quickly, so they put the less-frequently-updated SSMS out in its own installer.

(Did I get that right? Forgive me, I’m not a smart man.)

Using Numbers Tables with Older VersionsIf you’re not on SQL Server 2022 yet, you can create your own numbers table with any of these examples. Just make sure your numbers table has at least as many rows as the number of Ids you’re looking for. Here’s an example with a 100,000,000 row table:

DROP TABLE IF EXISTS dbo.Numbers;CREATE TABLE dbo.Numbers (Number INT PRIMARY KEY CLUSTERED); INSERT INTO dbo.Numbers(Number)SELECT TOP 10000000 row\_number() over(order by t1.number) as NFROM master..spt\_values t1 CROSS JOIN master..spt\_values t2 CROSS JOIN master..spt\_values t3GO Then, we’ll use that in a way similar to GENERATE_SERIES:

DECLARE @FirstId INT, @LastId INT;SELECT @FirstId = MIN(Id),@LastId = MAX(Id)FROM dbo.Users;SELECT n.NumberFROM dbo.Numbers nLEFT OUTER JOIN dbo.Users u ON n.Number = u.IdWHERE u.Id IS NULL AND n.Number > @FirstId AND n.Number < @LastIdORDER BY n.Number; That produces similar results, but not identical:

What’s different? Well, this method didn’t include 0! When I populated my numbers table, I only built a list of positive integers. The single most common mistake I see when using numbers tables is not having thorough coverage of all the numbers you need. Make sure it goes as low and as high as the values you need – a problem we don’t have with GENERATE_SERIES, since we just specify the start & end values and SQL Server takes care of the rest.

If you’d like to dive deeper into other ways to solve this problem, Itzik Ben-Gan’s chapter on Gaps & Islands will be right up your alley. Me, though, I’ll call it quits here because I’m in love with GENERATE_SERIES to solve this problem quickly and easily. Also, I’m lazy.

View Details

Here’s what I wrote in 2022 that gathered the most views:

  • 10: Who’s Hiring in the Database Community? February 2022 Edition – I saw the success of Hacker News’ “Who’s Hiring” monthly posts, and I blatantly stole the idea for the Microsoft data platform community. It works out well, very popular, very popular.

  • 9: PSPO: How SQL Server 2022 Tries to Fix Parameter Sniffing – I was so pissed off when I wrote this, and I’m sure y’all could tell.

  • 8: SQL Server 2022 Tells You Why A Query Can’t Go Parallel – such a simple thing, and so desperately needed.

  • 7: The Top Feature Requests for SQL Server – I publish these every now and then, but this year I managed to work in a few zingers at the end of the post.

  • 6: SQL Server 2022 Release Date: November 16, 2022 – this is one of those posts that will always get a lot of hits because people Google for it a lot.

  • 5: Breaking News: SQL Server 2019 CU16 Changes Backup Formats, Can Break Log Shipping – makes sense as to why this was popular because a lot of people still rely on log shipping.

  • 4: Columnstore Indexes are Finally Sorted in SQL Server 2022 – WHAT?!? How on earth did this end up in the top 10? I kinda think of columnstore as a niche topic.

  • 3: Designing a Data Model for Gender and Sexuality (Oh And Also, I’m Pansexual) – can’t imagine how this went viral. Was also the top-commented post of the year. Thank y’all for your support and kind words.

  • 2: Here Are The Results of the 2022 Data Professional Salary Survey – I’ll hazard a guess that a lot of y’all were switching jobs or asking for raises this year.

  • 1: Buckle Up: October is Free Fundamentals Month! – when I published this, I told readers to bookmark this page, and then come back every day to link to whatever video was free today. I didn’t realize people would absolutely hammer that page, hahaha!

Evergreen Posts You Kept ReadingThese aren’t posts I wrote in 2022 – they’re older posts that have stood the test of time, and keep showing up in Google results. These tutorial posts aren’t often the favorites of readers when the post first goes live, but they’re the kinds of posts that bring in new readers over time. I’ve gradually updated a lot of these (even if I wasn’t the original author) because they’re consistently popular.

  • 10: How to Make SELECT COUNT(*) Queries Crazy Fast (2019)

  • 9: Cheat Sheet: How to Configure TempDB for Microsoft SQL Server (2016)

  • 8: Implementing Snapshot or Read Committed Snapshot Isolation in SQL Server: A Guide by Kendra Little (2013)

  • 7: The Elephant and the Mouse, or, Parameter Sniffing in SQL Server by Jes Schultz (2013)

  • 6: How to Move TempDB to Another Drive & Folder (2017)

  • 5: How to Pass a List of Values Into a Stored Procedure (2020)

  • 4: How to Download the Stack Overflow Database (2015)

  • 3: How to Select Specific Columns in an Entity Framework Query by Richie Rump (2016)

  • 2: How to fix the error “String or binary data would be truncated” (2019)

  • And the #1 most popular post over time: How to count the number of rows in a table by Jes Schultz (2014)

Not only is it hard to write posts like this initially, but it takes work to continue to refine the content over time, adding in the kinds of key words and content that people are searching for. I actively prune some of ’em, and some of them were perfect when they were published.

Top YouTube Videos You WatchedMy YouTube channel got 560,871 views in 2022, with 101,500 watch hours and 39,000 subscribers. I have to confess that I do a terrible job of reminding viewers to smash that like button and hit the bell to be notified when new posts go live. I’m just not that kind of host – yet, hahaha.

  • 10: Office Hours on June 21, 2022 – I’m consistently amazed at how many thousands of people watch these videos every week, and I’m even more stunned that one of ’em cracked the top 10 overall!

  • 9: Execution Plan Operators by Doug Lane – part of a longer training class Doug was building. We ended up not shipping, so we just published what we did for free on YouTube.

  • 8: Identifying and Fixing Parameter Sniffing Issues – recorded live at SQLDay Poland 2017.

  • 7: Backups: 3 Common Strategies – VSS snapshots, native full backups, and log backups.

  • 6: What’s New in SQL Server 2019 – I should probably do one of these for 2022, come to think of it.

  • 5: An Introduction to Microsoft SQL Server’s Statistics – my attempt to be Alton Brown with overhead cameras, playing cards, and a notebook.

  • 4: Watch Brent Tune Queries at SQLSaturday Oslo – delivered remotely, recorded.

  • 3: Blocking and Locking: How to Find and Fight Concurrency Problems – recorded live at SQLDay Poland 2017.

  • 2: How to Think Like the Engine, Part 1 – a live version.

  • 1: Microsoft SQL Server Performance Tuning, Live – recorded live at Microsoft Ignite in 2015. I think it’s probably due to the title, which tells me I should do an updated one of these.

Here’s to a productive 2023 where I share a lot and y’all learn a lot!

View Details

Are your peers being paid more this year? Are they switching job roles? Are they planning on leaving their companies? To find out, I run a salary survey every year for folks in the database industry. Download the raw data here and slice & dice ’em to see what’s important to you.

Salaries are on the rise again this year:

If I filter the data for just the United States, they’re on the rise too:

And if I filter the data for just DBAs, the job title I’m usually most interested in, United States DBAs are on the rise by about 6% this year:

Nice! Congrats on the raises, y’all. (On the other hand, if you’re reading this, and you didn’t get a raise, now’s the time to download this data and start having a discussion with your manager.) You might also be considering switching jobs – so which job titles are getting the most this year?

Architects, app code developers, and managers are doing well. Note, though, that I’m filtering on just United States folks here, so the survey sample size is getting smaller. Plus, I would never make long term career decisions based on money alone – you might not be happy doing a particular job. (I hated management.)

Is any one job title growing at the expense of others? Are people leaving DBA work en masse and switching to something else? No, the mix by job title has been roughly the same over the years, despite what you might have heard from Thought Leaders™:

So why do you hear Thought Leaders™ saying one job role or another is dead, and another one is on fire? Because it’s a short-term publicity trend, sometimes as short as months, where a few publication outlets run the same stories and build buzz around something in order to get clicks.

Is there a mass resignation coming? What are peoples’ career plans for 2023, and have those numbers changed from prior years?

Most of you still want to stay with the same employer, in the same role. Well, in that case, here’s to a stable, safe 2023 for y’all.

View Details

Was your New Year’s resolution to get a new job? Heads up: the comments in this post are for you.

Is your company hiring for a database position as of January 2023? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment.

The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

Beep beep! Here’s a speed round of Office Hours where I rip through a dozen questions in under ten minutes. Want to see your own questions answered? Post ’em and upvote the ones you like at https://pollgab.com/room/brento.

  • 00:00 Start
  • 00:22 DB-A-Team: Love and appreciate your work and please don’t make fun of my question. I want to create a special DB related project in my workplace next year, that can give an extra value like automate code deployment using CI/CD, any more ideas you have as someone who sees a lot of clients?
  • 01:03 TooSarcastic: Any tips or advice to keep a poker face when hearing non-sense from clients or coworkers?
  • 01:31 Haydar: When performing the ‘A’ of D.E.A.T.H., how do you avoid adding beneficial index for costly query that is infrequently executed? 02:04 Crypto Bro: Do you see any good / common use cases for new SQL 2022 Ledger functionality?
  • 02:27 Rick James: What is your opinion of AlloyDB for PostgreSQL from Google? Is this the Aurora killer?
  • 03:03 Herb: What is your opinion of new sp_invoke_external_rest_endpoint functionality in Azure SQL DB?
  • 03:47 Clarence Oveur: Are SQL CLR Udf’s any better / more desirable than scalar Udf’s?
  • 04:18 neil: I just noticed developers have been setting Read Committed Snapshot to ON on their databases without telling anyone. Should I be concerned?
  • 04:38 Dru: Is coding first responder kit for multiple versions of SQL painful like coding JavaScript for multiple browser versions?
  • 05:12 NeverEndingView: If you are tuning a view that you cannot get to complete or show an actual execution plan, will adding a TOP give you the same plan as running without? I let the query run for 19 hours and never received a plan.
  • 05:46 Bob the Builder: What is the largest SQL Server single DB size you have ever seen? What challenges does that large size present?
  • 06:14 Curious DBA: Hi Brent. I know you no longer get involved with DR scenarios, but was wondering if you ever encountered a scenario where a Suspect database couldn’t be brought into Emergency Mode? A friend encountered this scenario recently but was able to recover from backups. Thanks.
  • 06:38 RSS_Fees: Alberto Morillo mentioned on StackOverflow a tool called Data Sync Agent for SQL Data Sync. I never heard about it before but apparently you can use it to migrate or sync data from on-prem to Azure SQL Database. Have you ever used it?

View Details

Ever wonder how fast people are adopting new versions of SQL Server, or what’s “normal” out there for SQL Server adoption rates, hardware sizes, or numbers of databases? Let’s find out in the winter 2022 version of our SQL ConstantCare® population report.

Out of 3,679 monitored servers, here’s the version adoption rate:

The big ones:

  • SQL Server 2019: 32% – taking the lead from SQL Server 2016 for the first time!
  • SQL Server 2017: 20%
  • SQL Server 2016: 27%
  • That combo is 79% of the population right there (83% with Azure), and it supports a ton of modern T-SQL, columnstore, etc features, so it’s a fun time to be building apps with T-SQL

Companies are leapfrogging right past SQL Server 2017. I’m going to hazard a guess that SQL Server 2017 came out too quickly after 2016, and didn’t offer enough features to justify upgrades from 2016.

Does that offer us any lessons for SQL Server 2022? Is 2022 going to be a 2017-style release that people just leapfrog over? Well, as I write this, it’s late December 2022, and I’m not seeing the widespread early adoption that I saw for 2019 where people had it in development environments ahead of the release, learning how to use it.

Me personally, one of the most awesome features of 2022 is the ability to fail back and forth between SQL Server and Azure SQL DB Managed Instances. However, that feature is still in limited public preview that requires a signup. Combine that with the fact that both 2022 and Managed Instances have really low adoption rates, and … I just don’t think this feature is going to catch on quickly. (As a blogger/speaker/trainer, that’s useful information, too – I only have so many hours in the day, and I gotta write material for things I think people are actually going to adopt.)

Okay, next up – adoption trends over time. You’re going to be tempted to read something into this chart, but I need to explain something first: we saw a huge drop in Azure SQL DB users for SQL ConstantCare. In the past survey, we had exactly 500 Azure SQL DBs being monitored – and this round, it dropped to just 64. I talked briefly with a couple of the SaaS customers who stopped monitoring their databases, and they both said the same thing: “We’re not going to change the app’s code or indexes based on what you found, so we’re not going to monitor it further.” That’s fair – throwing cloud at it is a perfectly legit strategy. So now, having said that, let’s see the trends:

This quarter’s numbers are a little misleading because it looks like SQL Server 2019 stole Azure’s market share – but now you know why. If I look at pure installation numbers (not as a percentage):

  • We finally have a customer using SQL Server on Linux in production! It’s only one, but … still, I’m excited about that because I can dig into their diagnostic data and figure out which recommendations aren’t relevant for them.
  • Azure SQL DB Managed Instances stayed steady (but it’s still a tiny number relative to the overall population)
  • SQL Server 2019 definitely grew, and every other version went down
  • There are only 6 instances of SQL Server 2022 (and several of those are Development Edition)

The low early adoption rate of 2022 is more interesting to me when I combine it with another number: Availability Groups adoption is 26%, kinda. Of the production SQL Servers that can (2012 & newer, non-Azure, etc), 26% have turned on the Always On Availability Groups feature. Note that I didn’t say 26% of databases are protected, nor 26% of data volume – just 26% of the servers have the feature turned on, period, and that says something because the feature isn’t on by default, and requires a service restart to take effect. Actual databases protected is way, way less.

One of SQL Server 2022’s flagship features is Managed Instance link, the ability to fail over databases back & forth between your SQL Server 2022 instances and Azure SQL DB Managed Instance. In theory, that’s awesome. In practice, I’ve never seen a concise live demo setting it up, failing it over, and failing it back. The setup part 1 and part 2 doesn’t look terrible, and the failover looks fairly straightforward, but … there are no docs on troubleshooting it. Between the low adoption rates, the complexity of existing AGs, the complexity of cloud networking, and this brand new feature, I’m … not ready to dig into Managed Instance link anytime soon.

I totally appreciate those of y’all who have the guts to try it, though, especially in production. I think that kind of thing is the future of hybrid databases. Looking at the current population numbers, though, it’s a pretty far-off future.

View Details

Y’all post questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me discuss, and then I artfully dodge giving you answers. At least, that’s how it feels sometimes, hahaha:

Here’s what we discussed in today’s episode:

  • 00:00 Start
  • 00:20 Piotr: Do many of your clients disable SA account for security? What are your thoughts on this practice?
  • 01:32 I was never given a name: What are your thoughts on using AI to generate SQL queries? OK for ad-hoc reporting, not for production? Specifically Ask Edith which is geared towards transforming English to SQL and ChatGPT.
  • 02:55 chandwich: Hey Brent! What’s your “go to” note taking app? I know you use Markdown, but is that all you use to improve note taking?
  • 03:24 Ólafur: What are some good ways to identify all NC indexes that could exceed the max key length of 1700 bytes in SQL 2019?
  • 04:06 Namor: Should SQL affinity mask be used/configured when SSRS / SQL Server are running on the same server so that each process gets it’s own processor?
  • 05:01 Sune Berg Hansen : Hey Brent, What features are no longer worth investing time in learning from a Admin or developer perspective? I have a coworker who still uses Server Side Tracing.
  • 05:57 Gustav: If you had to give a razzie award for worst performing cloud storage for VM SQL, which cloud vendor would win the award?
  • 06:57 Stockburn: Hi Brent, I assume you have needed to use a plan guide at some point in your career but at what point in a performance investigation do you decide this is the way to solve the problem? As always thank you for all you do for us SQL folk!
  • 08:58 Sune Berg Hansen : Yo Brent, What are your top 3 favorite movies?
  • 09:15 Lazze-SeniorAppDeveloper-JuniorDBA: Hi, We have a server with high cpu load ( 8 cores ) and high wait stats for parallelism(sql Enterprise 2019) + CPU Yield. MaxDOP 8, CTFP 50 – I’m thinking about decreasing MaxDop to 4 or maybe even 2, to leave more cores free to run other queries and help the wait stats?
  • 10:30 Yitzhak: How do you determine the optimal autogrowth size for a given data file? One server is on expensive SAN storage while the other is on cheaper cloud storage.

View Details

If you’ve been following along with this week’s posts on DATETRUNC and STRING_SPLIT, you’re probably going to think the answer is no, but bear with me. It’s Christmas week, right? The news can’t all be bad.

GREATEST and LEAST are kinda like MAX and MIN, but instead of taking multiple rows as input, they take multiple columns. For example:

SELECT GREATEST(1,2,3) AS TheGreatest,LEAST(1,2,3) AS TheLeastest; Produces 3 and 1. This actually has really useful real-world implications.

Let’s take the Stack Overflow database, and let’s say I want to find any posts (questions or answers) that had recent activity. This is surprisingly difficult because Posts has 2 date columns: LastEditDate, and LastActivityDate. You would think that LastActivityDate would be the most recent, but you would be incorrect – when posts are edited, the LastEditDate is set, but LastActivityDate is not.

So if I was looking for any Posts that were active – either via reader activity, or edits – in a date range, I used to have to build supporting indexes, and then write queries like this:

/* Create supporting indexes */CREATE INDEX LastActivityDate\_LastEditDateON dbo.Posts(LastActivityDate, LastEditDate);CREATE INDEX LastEditDate\_LastActivityDateON dbo.Posts(LastEditDate, LastActivityDate);GO/* The old way: */SELECT TOP 200 *FROM dbo.PostsWHERE LastActivityDate >= '2018-05-27' OR LastEditDate >= '2018-05-27'ORDER BY Score DESC;/* The SQL Server 2022 way: */SELECT TOP 200 *FROM dbo.PostsWHERE GREATEST(LastActivityDate, LastEditDate) >= '2018-05-27'ORDER BY Score DESC; I’m using 2018-05-27 because my copy of the Stack Overflow database’s last activity is in 2018-06-03. Depending on which version you’re using, if you’re trying to reproduce these results, pick a date that’s within the last week of activity

So, what’s better – the old way or the new way? Like your hips, the actual execution plans don’t lie:

The old way smokes the SQL Server 2022 way. I mean, it’s not even close. The old way splits up the work into two index seeks, one on LastActivityDate and one on LastEditDate. It finds the recent stuff, does the appropriate key lookups, and it’s done in one second.

The new way does a table scan and takes a minute and a half.

Its estimates and its index usage are just garbage, and I don’t mean like Shirley Manson.

Again – they’re not necessarily bad functions, but they have no business in the FROM clause and below. Don’t use them in WHERE, don’t use them in JOINS, just use them to construct output, variables, and strings.

View Details

SQL Server 2022 improved the STRING_SPLIT function so that it can now return lists that are guaranteed to be in order. However, that’s the only thing they improved – there’s still a critical performance problem with it.

Let’s take the Stack Overflow database, Users table, put in an index on Location, and then test a couple of queries that use STRING_SPLIT to parse a parameter that’s an incoming list of locations:

CREATE INDEX Location ON dbo.Users(Location);SET STATISTICS IO ON;GOCREATE OR ALTER PROC dbo.usp\_GetUsersByLocation\_Subquery@LocationList NVARCHAR(4000) ASSELECT TOP 1000 u.*FROM dbo.Users uWHERE u.Location IN (SELECT value FROM STRING\_SPLIT(@LocationList, N',', 1))ORDER BY u.Reputation DESC;GOCREATE OR ALTER PROC dbo.usp\_GetUsersByLocation\_Join@LocationList NVARCHAR(4000) ASSELECT TOP 1000 u.*FROM STRING\_SPLIT(@LocationList, N',', 1) lINNER JOIN dbo.Users u ON l.value = u.LocationORDER BY u.Reputation DESC;GOEXEC usp\_GetUsersByLocation\_Subquery N'India,China';EXEC usp\_GetUsersByLocation\_Join N'India,China'; The two queries produce slightly different actual execution plans, but the way STRING_SPLIT behaves is the same in both, so I’m just going to take the first query to use as an illustration:

That red-highlighted part has two problems:

  1. SQL Server has no idea how many rows are going to come out of the string, so it hard-codes a guesstimate of 50 items
  2. SQL Server has no idea what the contents of those rows will be, either – it doesn’t know if the locations are India, China, or Hafnarfjörður

As a result, everything else in the query plan is doomed. The estimates are all garbage. SQL Server will choose the wrong indexes, process the wrong tables first, make the wrong parallelism decisions, be completely wrong about memory grants, you name it.

Like I wrote in this week’s post about DATETRUNC, that doesn’t make STRING_SPLIT a bad tool. It’s a perfectly fine tool if you need to parse a string into a list of values – but don’t use it in a WHERE clause, so to speak. Don’t rely on it to perform well as part of a larger query that involves joins to other tables.

Working around STRING_SPLIT’s problemsOne potential fix is to dump the contents of the string into a temp table first:

CREATE OR ALTER PROC dbo.usp\_GetUsersByLocation\_TempTable@LocationList NVARCHAR(4000) ASBEGINSELECT valueINTO #LocationListFROM STRING\_SPLIT(@LocationList, N',', 1);SELECT TOP 1000 u.*FROM dbo.Users uWHERE u.Location IN (SELECT value FROM #LocationList)ORDER BY u.Reputation DESC;ENDGOEXEC usp\_GetUsersByLocation\_TempTable N'India,China'; And the actual execution plan is way better than the prior examples. You can see the full plan by clicking that link, but I’m just going to focus on the relevant STRING_SPLIT section and the index seek:

This plan is better because:

  • SQL Server knows how many rows are in #LocationList
  • Even better, it knows what those rows are, and that influences its estimate on the number of users who live in those locations, which means
  • SQL Server makes better parallelism and memory grant decisions through the rest of the plan

Woohoo! Just remember that temp tables are like OPTION (RANDOM RECOMPILE), like I teach you in this Fundamentals of TempDB lecture.

View Details

SQL Server 2022 introduced a new T-SQL element, DATETRUNC, that truncates parts of dates. For example:

SELECT DATETRUNC(year, '2017-06-01'); Truncates everything in that date other than the year, so it returns just 2017-01-01 00:00:

You might ask, “Well, why not just use YEAR()?” That’s a good question – there are times when you need a start or end date for a date range, and this could make it easier than trying to construct a full start & end date yourself.

Easier for you, that is – but not necessarily good for performance. Let’s take the Stack Overflow database, Users table, put in an index on LastAccessDate, and then test a few queries that are logically similar – but perform quite differently.

CREATE INDEX LastAccessDate ON dbo.Users(LastAccessDate);SET STATISTICS IO ON;GOSELECT COUNT(*) FROM dbo.UsersWHERE LastAccessDate >= '2017-01-01' AND LastAccessDate < '2018-01-01';SELECT COUNT(*) FROM dbo.UsersWHERE YEAR(LastAccessDate) = 2017;SELECT COUNT(*) FROM dbo.UsersWHERE DATETRUNC(year, LastAccessDate) = 2017; And check out their actual execution plans:

The first one, passing in a specific start & end date, gets the best plan, runs the most quickly, and does the least logical reads (4,299.) It’s a winner by every possible measure except ease of writing the query. When SQL Server is handed a specific start date, it can seek to that specific part of the index, and read only the rows that matched.

DATETRUNC and YEAR both produce much less efficient plans. They scan the entire index (19,918 pages), reading every single row in the table, and run the function against every row, burning more CPU.

SQL Server’s thought process is, and has always been, “I have no idea what’s the first date that would produce YEAR(2017). There’s just no way I could possibly guess that. I might as well read every date since the dawn of time.”

That’s idiotic, and it’s one of the reasons we tell ya to avoid using functions in the WHERE clause. SQL Server 2022’s DATETRUNC is no different.

So why doesn’t Microsoft fix this?YEAR and DATETRUNC are tools, just like any other tool in the carpenter’s workshop. There are lots of times you might need to manipulate dates:

  • When constructing a dynamic SQL string, and you want to build a date – sure, using a function to build the WHERE clause string is fine. Just don’t use the function in the WHERE clause itself.
  • When constructing the contents of variables
  • When constructing the output of the query – sure, using a function like this in the SELECT is fine, because it doesn’t influence the usage of indexes in the query plan

DATETRUNC in the SELECT isn’t so bad.Let’s use it in the SELECT clause to group users together by their last access date. Say we want a report to show trends over time. Here are two ways to write the same basic idea of a query:

SELECT YEAR(LastAccessDate) AS CreationYear,MONTH(LastAccessDate) AS CreationMonth,SUM(1) AS UsersInvolvedFROM dbo.UsersGROUP BY YEAR(LastAccessDate), MONTH(LastAccessDate)ORDER BY 1, 2;SELECT DATETRUNC(MONTH, LastAccessDate) AS CreationMonth,SUM(1) AS UsersInvolvedFROM dbo.UsersGROUP BY DATETRUNC(MONTH, LastAccessDate)ORDER BY 1; The two queries do show the date in two different ways, but the UsersInvolved count is the same – it’s just different ways of rendering the same data:

When you review their actual execution plans, the first one (YEAR/MONTH) is much more complex, and goes parallel to chew through about 4 seconds of CPU time:

Whereas the new DATETRUNC syntax has a cool benefit: it only produces one value (the date), and the data in the index is already sorted by that column. Because of that, we don’t need an expensive sort in the execution plan. And because of that, we don’t need parallelism, either, and we only chew through about two seconds of CPU time. Nifty!

So should you use DATETRUNC? Like with most functions, the answer is yes in the select, but probably not in the FROM/JOIN/WHERE clauses.

View Details

Every time I think, “There can’t be any more SQL Server questions left,” y’all post more great ones at https://pollgab.com/room/brento!

Here’s what we covered:

  • 00:21 MattC: Hi Brent. Have you check out ChatGPT’s ability to write SQL code. VERY impressive and in some cases faster than a stackoverflow question. In fact stackoverflow have had to ban people using GPT to answer peoples questions
  • 02:28 Haddaway: Does high VLF count matter when it is in TempDB? sp_blitz reports 1000 VLF’s for TempDB.
  • 04:33 Yousef: Is GUID data type a good clustered index when concurrent inserts are high?
  • 05:51 Prohiller: Hi Brent, is there any reason why not enable automatic page repairs in my AGs? Any gotchas MS documentation isn’t mentioning?
  • 06:21 DavDBA: Hey Brent, I want to do some maintenance work on my server and was wondering Does one of the blitz scripts finds invalid objects at a Server/DB level?
  • 06:56 Wendigo: When modifying columns in SSMS table designer, why does “Generate change script” like to copy all the existing data to a new temp table, then swap the tables as opposed to just altering the column directly?
  • 07:54 The Purge Police: Any tips for identifying all tables that are growing unbounded without retention policies?
  • 08:50 Hrafnhildur: What SQL Prompt features would you like to see included in future versions of SSMS / Azure Data Studio?
  • 10:42 Dr. Ruth: What are some recommended techniques for identifying sprocs that are no longer used? Have hundreds of sprocs but not all still used and would like to clean up.
  • 12:07 Fyodor: Is it ever OK to use the leading columns of the clustered index as the leading columns for some of the non-clustered indexes? Any gotcha’s with this?
  • 13:03 Culloden: I keep seeing MS invest in Storage Spaces Direct. Why would one decide to put SQL Server on commodity hardware? I’ve only worked at organizations with large prod servers that use SANs for storage.
  • 14:31 coffee_table: Hello! what are the gotchas with doing hourly incremental loads to a data warehouse rather than a single overnight load? Would statistics always be misleading? Doug Lane Videos on your channel suggest that a filtered stats might be a solution. Thoughts?

View Details

Santa’s elves took a break from building toys and shipped a new version of the First Responder Kit. There are some great improvements in here, like a makeover for sp_BlitzLock and much better PSPO compatibility for sp_BlitzCache.

Wanna watch me use it? Take the class.To get the new version:

  • Download the updated FirstResponderKit.zip
  • Azure Data Studio users with the First Responder Kit extension:
    ctrl/command+shift+p, First Responder Kit: Import.
  • PowerShell users: run Install-DbaFirstResponderKit from dbatools
  • Get The Consultant Toolkit to quickly export the First Responder Kit results into an easy-to-share spreadsheet

Consultant Toolkit ChangesI updated it to this month’s First Responder Kit, but no changes to querymanifest.json or the spreadsheet. If you’ve customized those, no changes are necessary this month: just copy your spreadsheet and querymanifest.json into the new release’s folder.

sp_AllNightLog Changes* Fix: if a database exists and it’s not being log shipped, skip it rather than overwrite it. (#3187, thanks David Wiseman.)

sp_Blitz Changes* Fix: date conversion errors on non-US environments. (#3161, thanks Christian Specht and Ralf Pickel.)

sp_BlitzCache Changes* Enhancement: show a statement’s parent stored procedure where available in SQL Server 2022 to work around the PSPO problem. (#3176, thanks Cody Konior.) * Fix: if you asked for the output of @SortOrder = ‘unused grant’ to be written to table, it wasn’t working. (#3160, thanks Petr-Starichenko.)

sp_BlitzFirst Changes* Fix: Managed Instances were getting errors on Perfmon counters. (#3184, thanks Cody Konior.) * Fix: lock timeout errors from sp_msforeachdb. (#3180, thanks Cody Konior.)

sp_BlitzIndex Changes* Enhancement: added support for output to table for all modes. (#2774, thanks Tor-Erik Hagen.) * Fix: the columnstore index visualization wasn’t filtering out tombstone rowgroups. (#3189) * Fix: statistics with oddball names would throw errors. (#3162, thanks Jay Holliday.)

sp_BlitzLock Changes* Enhancement: in Erik’s words, he gave the T-SQL a mommy makeover, including the ability to read from the ring buffer, improve performance, fix data duplicatoin bugs, clean XML to avoid character parsing errors, etc. (#3166, thanks Erik Darling.)

sp_BlitzQueryStore Changes* Fix: errors on TRY_CONVERT for databases in compat level 100. (#3155, thanks ray13eezy and Erik Darling.)

sp_BlitzWho Changes* Enhancement: move session_id and blocking_session_id next to each other for easier blocking troubleshooting. (#3159, thanks David Hooey.)

sp_DatabaseRestore Changes* Fix: full backups with more than 9 files were being ignored. (#3156, thanks Wilfred van Dijk.) * Fix: wasn’t working on SQL Server 2022 due to new undocumented columns. (#3190)

Bonus changes: Anthony Green kept up the tireless work of keeping the SQL Server versions file up to date.

For SupportWhen you have questions about how the tools work, talk with the community in the #FirstResponderKit Slack channel. Be patient: it’s staffed by volunteers with day jobs. If it’s your first time in the community Slack, get started here.

When you find a bug or want something changed, read the contributing.md file.

When you have a question about what the scripts found, first make sure you read the “More Details” URL for any warning you find. We put a lot of work into documentation, and we wouldn’t want someone to yell at you to go read the fine manual. After that, when you’ve still got questions about how something works in SQL Server, post a question at DBA.StackExchange.com and the community (that includes me!) will help. Include exact errors and any applicable screenshots, your SQL Server version number (including the build #), and the version of the tool you’re working with.

View Details

Wow, y’all have been posting some great questions at https://pollgab.com/room/brento lately!

Here’s what we covered today:

  • 00:59 Gustav: Hi Brent We recently migrated to SQL MI General Purpose, and I noticed that the default blob storage per .mdf /.ndf file is 128Gb container with 500 IOPS! This is terribly slow! Would splitting the database into multiple files, increase read / write performance?
  • 02:39 PAAREES: Is it normal getting corruption like errors if you stop a running dbcc checkdb and getting no errors if you let it finish in the same db/vm ?
  • 03:07 MancDBA: Hi Brent, Over the years, have you ever felt blogging and giving back so much to the community (for free) has ever been a thankless task especially if people are mean to you? Cheers!
  • 04:40 Len: What criteria do you use for deciding which tables need more/less statistic updates, which tables need full scan vs sampled scan?
  • 07:30 Namor: How does the PostgreSQL DBA learning track compare with SQL Server (width, depth, difficulty)?

View Details

Is your company hiring for a database position as of December 2022? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment.

The rules:

  • Your comment must include the job title, and either a link to the full job description, or the text of it. It doesn’t have to be a SQL Server DBA job, but it does have to be related to databases. (We get a pretty broad readership here – it can be any database.)
  • An email address to send resumes, or a link to the application process – if I were you, I’d put an email address because you may want to know that applicants are readers here, because they might be more qualified than the applicants you regularly get.
  • Please state the location and include REMOTE and/or VISA when that sort of candidate is welcome. When remote work is not an option, include ONSITE.
  • Please only post if you personally are part of the hiring company—no recruiting firms or job boards. Only one post per company. If it isn’t a household name, please explain what your company does.
  • Commenters: please don’t reply to job posts to complain about something. It’s off topic here.
  • Readers: please only email if you are personally interested in the job.

If your comment isn’t relevant or smells fishy, I’ll delete it. If you have questions about why your comment got deleted, or how to maximize the effectiveness of your comment, contact me.

Each month, I publish a new post in the Who’s Hiring category here so y’all can get the latest opportunities.

View Details

I was helping a client with a query, and I’m going to rework the example to use the Stack Overflow database for easier storytelling. Say we need to: Find all the locations where users have logged in since a certain date, then Return the total count of people who live in those locations One way...

View Details

I took a break from my Black Friday sale customer support emails to check in on the questions you posted at https://pollgab.com/room/brento and answer the highest-voted ones: 00:00 Start 00:15 Meshulam: What are the top use cases for running SQL Server in a container? Do many of your customers run SQL Server in a container?...

View Details

My Black Friday sale is in its last days, so most of my time at the moment is spent keeping an eye on the site and answering customer questions. I’m happy to say it’s our best year so far, too! Y’all really like the new access-for-life options. I took a break from the online frenzy to...

View Details

When will Microsoft officially release SQL Server 2023 (or 2024, or whatever it’ll be) for download? The dust is just barely starting to settle on the 2022 box, so it’s time to guess the next one. Leave one – and only one – comment here in YYYY/MM/DD format with your release date guess. If you...

View Details

Whew. This is a crazy time, isn’t it? The aftermath of the pandemic is kicking in, and there are layoffs happening in Silicon Valley companies, but… the data profession is on fire. I don’t know anyone who’s been out of work for too long because companies are so desperate to get data help. So it’s time...

View Details

I’m back home in Vegas, back down to Inbox Zero, and I’ve had some time to think about last week’s conference in Seattle. I liveblogged the keynotes, but I wanted to talk about the conference overall. This was Redgate’s first time running an in-person Summit after the professional organization folded in December 2020. Redgate bought...

View Details

Today at the PASS Data Community Summit in Seattle, Kimberly Tripp is doing the first-ever in-person community keynote. Here’s the abstract: Over the 30+ years I’ve been working with SQL Server, I’ve seen an incredible amount of innovation and change. How do we keep up with so many changes and how do we know how...

View Details

I’m in Seattle for the PASS Data Community Summit, and the day 2 keynote is about to start. This year, now that Redgate owns the Summit event, they’re doing the day 2 keynote. Gotta pay the bills, I suppose! Redgate’s CEO, Jakub Lamik, is leading a team of speakers for the keynote, and here’s the...

View Details

For the final release of SQL Server 2022, Microsoft popped a surprise that wasn’t in the release candidates: Your choices are: Install a free edition: Evaluation (which times out after 180 days), Developer (which isn’t allowed to be used for production purposes), or Express (which is limited to small databases & hardware resources) Use pay-as-you-go-billing,...

View Details

If you’ve been reading this blog for a while or subscribed to my email newsletters, you’ve learned something from Hugo Kornelis. Hugo is the wildly productive and selfless guy behind the Execution Plan Reference, SQLServerFast.com, tons of SQLBits sessions, videos on YouTube, and he’s @Hugo_Kornelis. He’s unbelievably upbeat and positive. He loves what he does, and...

View Details

Microsoft released SQL Server 2022 today, November 16, 2022. The footnotes indicate: SQL Server 2022 free editions (Developer edition, Express edition) are available to download starting today. SQL Server 2022 paid editions (Enterprise edition, Standard edition) will be available in Volume Licensing (Enterprise Agreement, Enterprise Agreement Subscriptions) customers starting today, which represents the majority of...

View Details

I’m in Seattle for the biggest annual gathering of Microsoft data platform professionals, the PASS Data Community Summit. This is the first in-person Summit since the pandemic, and the first since Redgate took over ownership from the old PASS organization. I’m really excited – this is like a family reunion for me. Microsoft’s Rohan Kumar...

View Details

I think I’ve found a bug in SQL Server setup’s MAXDOP calculation, and I need you to take a second look. Setup is recommending MAXDOP 8: Which is odd, because this is running on an AWS i3.16xlarge with 2 sockets, 2 NUMA nodes, 32 logical processors per node, 64 logical processors altogether. In this screenshot, I’ve laid...

View Details

Is your company hiring for a database position as of November 2022? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment. The rules: Your comment must include the job title, and either a link to the full...

View Details

Ask questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me cover. Here’s what we covered today: 00:00 Start 00:59 neil: is it dangerous/risky to expand a drive in azure with SQL data files on it? sql on azure vm. dont know what happens behind the scenes 02:07 Brett: I am a consultant...

View Details

Post your questions at https://pollgab.com/room/brento and upvote the ones you’d like to see me discuss during my live streams. This week, I took a break from working on my PASS Summit sessions in order to chat: Here’s what we covered: 00:00 Start 00:32 Jeremy: We have an older web app we’re going to be rewriting...

View Details

This month on the blog is Community Tools Month, and I’m going to be talking about some of the most useful and influential tools out there. You can’t learn them all – I can’t learn them all – because there just aren’t enough hours in the day to do your work, keep your skills sharp,...

View Details

Not all of the questions y’all post at https://pollgab.com/room/brento require long, thought-out answers. Some are just one-line specials, like these: F’legend: Hi Brent, in reply to a question talking about database restores for 1TB+ you also touched on scrubbing or synthetic data as a way to populate dev environments. Are there any resources/tools you would...

View Details

Is your company hiring for a database position as of September 2022? Do you wanna work with the kinds of people who read this blog? Let’s set up some rapid networking here. If your company is hiring, leave a comment. The rules: Your comment must include the job title, and either a link to the full...

View Details

What does fragmentation mean? How does it happen? Can you fix it with fill factor? Should you rebuild your indexes to fix it? At the SQLBits conference, I tried a new way of explaining it using markers and pieces of whiteboard paper as database pages, and doing inserts live on the fly. What you see...