ContentsThe library

Why a Query Is Slow

The Three Ways to Join

Last timeThe Plan Is Built on a Guess

There are only three ways to match rows in one table against rows in another, each wins in a different situation, and most slow joins are the wrong one of the three.

Joining is where queries go from slow to unusable, because the three available

methods differ not by a few percent but by factors of thousands. Every database

has all three, and the whole art is in which one gets used.

FIG 1How the method gets chosen
The branches are decided before any data is read. Nothing in this diagram measures anything, which is why the quality of the estimates from the previous topic determines which of three wildly different performances you get.

One row at a time

The simplest method takes the first row of one side, searches the other side for

rows matching it, emits the matches, and moves on. The side being walked is the

outer side; the side being searched is the inner.

Its cost is the number of outer rows multiplied by the cost of one search, and

that multiplication is the whole story. Twelve outer rows against an indexed

inner side costs almost nothing. Two million outer rows is two million index

descents, and if the inner side has no usable index, two million full scans,

which is the worst thing a database can be made to do.

FIG 2What looking rows up one at a time costs
the total time for the join
the number of rows on the outer side, the one being walked
the cost of one descent into the inner side's index
the number of matching rows found per outer row
the cost of fetching one matching row, which is a scattered read
the shape that matters, a cost strictly proportional to the outer side, with nothing in it that improves as the join gets bigger
There is no term here that flattens. Every other method reads each side a fixed number of times, so their costs grow far more slowly, which is why this method is either the best available or very much the worst.

Building a lookup structure

The second method reads one side completely and arranges it in memory so that

any value can be found immediately. Then it reads the other side once, looks each

row up, and emits what matches.

The accounting is completely different. Each side is read exactly once, and the

probing side's rows cost almost nothing each, so this is the default for joining

two large tables and usually what you want to see in a plan.

The condition is memory. What has to fit is not the table but the rows and

columns the query uses from it.

The lesson stops here

4 more paragraphs to go

You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.

The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.

See the planThe contents

This is the reading half

Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.

The contents

The rest of this course

  1. 01What a Query Is Actually Spending
  2. 02What an Index Actually Isopening only
  3. 03The Conditions No Index Can Rescueopening only
  4. 04Every Plan Rests on an Estimateopening only
  5. 05The Three Ways to Joinyou are here
  6. 06How to Read a Planopening only
  7. 07The Bill for Every Indexopening only
  8. 08A Method Instead of a Guessopening only

Read alongside