Press "Enter" to skip to content

Category: Query Tuning

Join Operator Properties and Query Performance

Andy Brownsword takes a closer look at the big three join operators in SQL Server:

In the previous post I explained Join Operators in SQL Server. Whilst compiling that I dug a little deeper and came across a few interesting points I thought were worth sharing.

Let’s look at behaviour of the operators which may occur under specific conditions. Hopefully you find them as interesting as I did:

Click through for an interesting tidbit about nested loops joins, merge joins, and hash joins.

Leave a Comment

Row and Range Frames in Window Functions and Batch Mode

Erik Darling covers how your window frame (that is, ROWS or RANGE in the window function definition) can affect batch mode.

Erik looks at a classic performance difference between ROWS and RANGE, as well as what batch mode does to even the score. This is particularly nice because ROWS and RANGE both have their utility and focusing on one versus the other for performance differences can lead to awkward development practices to get around a window spool.

Erik also focuses primarily on batch mode on rowstore, so keep in mind the minimum requirements for it: 131,072 (or 2^17) rows in at least one table in the query, at least one operator that benefits from batch mode (which we’d cover in the window function), at least one input of the batch with 2^17 rows, and where the batch mode cost is lower than the row mode cost.

Leave a Comment

Digging Further into RTABench Q0 Optimization on PostgreSQL

Andrei Lepikhov responds to feedback:

In the previous post, I explored some nuances of Postgres related to indexes and parallel workers. This text sparked a lively discussion on LinkedIn, during which one commentator (thanks to Ants Aasma) proposed an index that was significantly more efficient than those discussed in the article. However, an automated comparison of EXPLAINs did not clarify the reasons for its superiority, necessitating further investigation.

Click through for the index and what Andrei learned along the way.

Leave a Comment

Making Leading Wildcard Searches Faster

Brent Ozar flips everything around:

99.9% of you are never gonna need this.

But let’s say you need to run queries with leading (not trailing) wildcards, like this search for all the different national versions of the Encabulator, each of which has different prefixes depending on which government it’s being sold to:

This is indeed a pretty uncommon scenario. I’m pretty sure I’ve only ever needed to do this once. Well, twice, but in one case I couldn’t actually use the REVERSE() function because the column was itself an awful non-deterministic function and this solution wouldn’t work.

Leave a Comment

Performance Optimizing PostgreSQL for RTABench Q0

Andrei Lepikhov gets under the hood:

I wanted to explore whether Postgres could be improved by thoroughly utilising all available tools, and for this, I chose the RTABench benchmark. RTABench is a relatively recent benchmark that is described as being close to real-world scenarios and highly selective. One of its advantages is that the queries include expressions involving the JSONB type, which can be challenging to process. Additionally, the Postgres results on RTABench have not been awe-inspiring.

Ultimately, I decided to review all of the benchmark queries, and fortunately, there aren’t many, to identify possible optimisations. However, already on the zero query, there were enough nuances that it was worth taking it out into a separate discussion.

Click through for a dive into this particular query and what Andrei did and some of the lessons you can draw from it.

Comments closed

The Virtue of Pagination

Brent Ozar recommends a strategy:

When I’m tuning queries, the normal answer is to make the query perform better – either via changing the T-SQL, adding hints, or adding indexes so that the data’s better prepared for the query.

However, sometimes when I’m looking at the output of sp_BlitzCache, I scroll across to the Average Rows column and double-check that the query’s actually returning a reasonable number of rows out in the wild.

Click through for some horror stories and the benefits of pagination. Brent’s last case was a scenario in which people received 1000 rows and nobody ever complained. I’ve worked in systems where the customers did want and need every row. And in those cases, pagination still works. Because 85-90% of customers only need the first page or two.

Now, I wish that OFFSET/FETCH actually performed well. Sadly, it generally is a dog when you work with larger datasets and get past the first few pages. That’s because if you want to show rows 10,000-10,050, you first need to scan from rows 1-9999 and throw that data away, then grab the 50 rows you need. There are some clever sorting tricks you can use to reduce the pain level on repeated fetch operations, and I show one of them in this demo script (scroll down to the OFFSET/FETCH demo, number 6 in the list). The prior key approach is, in my experience, the best performer but it assumes you only move in one direction and don’t allow users to select arbitrary page numbers or go straight to the end.

1 Comment

Common Table Expressions in SQL Server and Materialization

Vlad Drumea is back to following Betteridge’s Law of Headlines and the people rejoice:

There’s this weird misconception floating around LinkedIn and reddit that SQL Server CTEs somehow store results in either memory or tempdb.

This is wrong and whoever states that CTEs store results either have no idea what they’re talking about or are intentionally trying to mislead people for engagement farming.

Click through for the proof of this.

As a quick note, you can materialize common table expressions in some relational database platforms like PostgreSQL, but SQL Server does not have that option.

Comments closed

Query Store Plan Forcing and RECOMPILE

Vlad Drumea tests Betteridge’s Law of Headlines:

It’s 3AM and I’m curious if Query Store plan forcing works on queries that use the RECOMPILE hint (aka OPTION(RECOMPILE) ).
So might as well make a blog post out of it.

Hmm, on the one hand, Vlad blatantly violates Betteridge’s Law of Headlines, which loses points. On the other hand, Vlad dunks hard on LLMs, gaining points. I’m so conflicted right now…

But not about reading Vlad’s post. Go read it.

1 Comment

Adaptive Joins and Equivalent Plans

Forrest McDaniel has a public service announcement:

In case you haven’t heard, moral decline is everywhere. The latest generation of query operators is a prime example of this rot. “But this is programming” you say, “what do morals have to do with anything?” No. This is SQL. And for us, we have the term morally equivalent plans which allows me to finally have an ethical excuse for sprinkling a post with degenerate puns.

I bit my tongue specifically to avoid doing exactly what Forrest does. So click through to read all of the terrible puns.

Comments closed