When an index beats a scan
The crossover selectivity is nothing but the ratio of sequential to random access cost.
- Matching pages
- pages the index must fetch (one per matching row when unclustered)
- Pages
- pages in the table
- Sequential cost
- cost of a sequential page read (seq_page_cost)
- Random cost
- cost of a random page read (random_page_cost)
How it behaves
One input on the horizontal axis, the others held fixed.
Data table
| Random ÷ sequential cost r/s | series | Crossover (share of rows) |
|---|---|---|
| 1 | row for row (f = 1) | 100% |
| 1.06 | row for row (f = 1) | 94.4% |
| 1.12 | row for row (f = 1) | 89.1% |
| 1.19 | row for row (f = 1) | 84.1% |
| 1.26 | row for row (f = 1) | 79.4% |
| 1.33 | row for row (f = 1) | 75% |
| 1.41 | row for row (f = 1) | 70.8% |
| 1.5 | row for row (f = 1) | 66.8% |
| 1.58 | row for row (f = 1) | 63.1% |
| 1.68 | row for row (f = 1) | 59.6% |
| 1.78 | row for row (f = 1) | 56.2% |
| 1.88 | row for row (f = 1) | 53.1% |
| 2 | row for row (f = 1) | 50.1% |
| 2.11 | row for row (f = 1) | 47.3% |
| 2.24 | row for row (f = 1) | 44.7% |
| 2.37 | row for row (f = 1) | 42.2% |
| 2.51 | row for row (f = 1) | 39.8% |
| 2.66 | row for row (f = 1) | 37.6% |
| 2.82 | row for row (f = 1) | 35.5% |
| 2.99 | row for row (f = 1) | 33.5% |
| 3.16 | row for row (f = 1) | 31.6% |
| 3.35 | row for row (f = 1) | 29.9% |
| 3.55 | row for row (f = 1) | 28.2% |
| 3.76 | row for row (f = 1) | 26.6% |
| 3.98 | row for row (f = 1) | 25.1% |
| 4.22 | row for row (f = 1) | 23.7% |
| 4.47 | row for row (f = 1) | 22.4% |
| 4.73 | row for row (f = 1) | 21.1% |
| 5.01 | row for row (f = 1) | 20% |
| 5.31 | row for row (f = 1) | 18.8% |
| 5.62 | row for row (f = 1) | 17.8% |
| 5.96 | row for row (f = 1) | 16.8% |
| 6.31 | row for row (f = 1) | 15.8% |
| 6.68 | row for row (f = 1) | 15% |
| 7.08 | row for row (f = 1) | 14.1% |
| 7.5 | row for row (f = 1) | 13.3% |
| 7.94 | row for row (f = 1) | 12.6% |
| 8.41 | row for row (f = 1) | 11.9% |
| 8.91 | row for row (f = 1) | 11.2% |
| 9.44 | row for row (f = 1) | 10.6% |
| 10 | row for row (f = 1) | 10% |
| 10.6 | row for row (f = 1) | 9.44% |
| 11.2 | row for row (f = 1) | 8.91% |
| 11.9 | row for row (f = 1) | 8.41% |
| 12.6 | row for row (f = 1) | 7.94% |
| 13.3 | row for row (f = 1) | 7.5% |
| 14.1 | row for row (f = 1) | 7.08% |
| 15 | row for row (f = 1) | 6.68% |
| 15.8 | row for row (f = 1) | 6.31% |
| 16.8 | row for row (f = 1) | 5.96% |
| 17.8 | row for row (f = 1) | 5.62% |
| 18.8 | row for row (f = 1) | 5.31% |
| 20 | row for row (f = 1) | 5.01% |
| 21.1 | row for row (f = 1) | 4.73% |
| 22.4 | row for row (f = 1) | 4.47% |
| 23.7 | row for row (f = 1) | 4.22% |
| 25.1 | row for row (f = 1) | 3.98% |
| 26.6 | row for row (f = 1) | 3.76% |
| 28.2 | row for row (f = 1) | 3.55% |
| 29.9 | row for row (f = 1) | 3.35% |
| 31.6 | row for row (f = 1) | 3.16% |
| 33.5 | row for row (f = 1) | 2.99% |
| 35.5 | row for row (f = 1) | 2.82% |
| 37.6 | row for row (f = 1) | 2.66% |
| 39.8 | row for row (f = 1) | 2.51% |
| 42.2 | row for row (f = 1) | 2.37% |
| 44.7 | row for row (f = 1) | 2.24% |
| 47.3 | row for row (f = 1) | 2.11% |
| 50.1 | row for row (f = 1) | 2% |
| 53.1 | row for row (f = 1) | 1.88% |
| 56.2 | row for row (f = 1) | 1.78% |
| 59.6 | row for row (f = 1) | 1.68% |
| 63.1 | row for row (f = 1) | 1.58% |
| 66.8 | row for row (f = 1) | 1.5% |
| 70.8 | row for row (f = 1) | 1.41% |
| 75 | row for row (f = 1) | 1.33% |
| 79.4 | row for row (f = 1) | 1.26% |
| 84.1 | row for row (f = 1) | 1.19% |
| 89.1 | row for row (f = 1) | 1.12% |
| 94.4 | row for row (f = 1) | 1.06% |
| 100 | row for row (f = 1) | 1% |
| 1 | 100 rows per page | 1% |
| 1.06 | 100 rows per page | 0.944% |
| 1.12 | 100 rows per page | 0.891% |
| 1.19 | 100 rows per page | 0.841% |
| 1.26 | 100 rows per page | 0.794% |
| 1.33 | 100 rows per page | 0.75% |
| 1.41 | 100 rows per page | 0.708% |
| 1.5 | 100 rows per page | 0.668% |
| 1.58 | 100 rows per page | 0.631% |
| 1.68 | 100 rows per page | 0.596% |
| 1.78 | 100 rows per page | 0.562% |
| 1.88 | 100 rows per page | 0.531% |
| 2 | 100 rows per page | 0.501% |
| 2.11 | 100 rows per page | 0.473% |
| 2.24 | 100 rows per page | 0.447% |
| 2.37 | 100 rows per page | 0.422% |
| 2.51 | 100 rows per page | 0.398% |
| 2.66 | 100 rows per page | 0.376% |
| 2.82 | 100 rows per page | 0.355% |
| 2.99 | 100 rows per page | 0.335% |
| 3.16 | 100 rows per page | 0.316% |
| 3.35 | 100 rows per page | 0.299% |
| 3.55 | 100 rows per page | 0.282% |
| 3.76 | 100 rows per page | 0.266% |
| 3.98 | 100 rows per page | 0.251% |
| 4.22 | 100 rows per page | 0.237% |
| 4.47 | 100 rows per page | 0.224% |
| 4.73 | 100 rows per page | 0.211% |
| 5.01 | 100 rows per page | 0.2% |
| 5.31 | 100 rows per page | 0.188% |
| 5.62 | 100 rows per page | 0.178% |
| 5.96 | 100 rows per page | 0.168% |
| 6.31 | 100 rows per page | 0.158% |
| 6.68 | 100 rows per page | 0.15% |
| 7.08 | 100 rows per page | 0.141% |
| 7.5 | 100 rows per page | 0.133% |
| 7.94 | 100 rows per page | 0.126% |
| 8.41 | 100 rows per page | 0.119% |
| 8.91 | 100 rows per page | 0.112% |
| 9.44 | 100 rows per page | 0.106% |
| 10 | 100 rows per page | 0.1% |
| 10.6 | 100 rows per page | 0.094% |
| 11.2 | 100 rows per page | 0.089% |
| 11.9 | 100 rows per page | 0.084% |
| 12.6 | 100 rows per page | 0.079% |
| 13.3 | 100 rows per page | 0.075% |
| 14.1 | 100 rows per page | 0.071% |
| 15 | 100 rows per page | 0.067% |
| 15.8 | 100 rows per page | 0.063% |
| 16.8 | 100 rows per page | 0.06% |
| 17.8 | 100 rows per page | 0.056% |
| 18.8 | 100 rows per page | 0.053% |
| 20 | 100 rows per page | 0.05% |
| 21.1 | 100 rows per page | 0.047% |
| 22.4 | 100 rows per page | 0.045% |
| 23.7 | 100 rows per page | 0.042% |
| 25.1 | 100 rows per page | 0.04% |
| 26.6 | 100 rows per page | 0.038% |
| 28.2 | 100 rows per page | 0.036% |
| 29.9 | 100 rows per page | 0.034% |
| 31.6 | 100 rows per page | 0.032% |
| 33.5 | 100 rows per page | 0.03% |
| 35.5 | 100 rows per page | 0.028% |
| 37.6 | 100 rows per page | 0.027% |
| 39.8 | 100 rows per page | 0.025% |
| 42.2 | 100 rows per page | 0.024% |
| 44.7 | 100 rows per page | 0.022% |
| 47.3 | 100 rows per page | 0.021% |
| 50.1 | 100 rows per page | 0.02% |
| 53.1 | 100 rows per page | 0.019% |
| 56.2 | 100 rows per page | 0.018% |
| 59.6 | 100 rows per page | 0.017% |
| 63.1 | 100 rows per page | 0.016% |
| 66.8 | 100 rows per page | 0.015% |
| 70.8 | 100 rows per page | 0.014% |
| 75 | 100 rows per page | 0.013% |
| 79.4 | 100 rows per page | 0.013% |
| 84.1 | 100 rows per page | 0.012% |
| 89.1 | 100 rows per page | 0.011% |
| 94.4 | 100 rows per page | 0.011% |
| 100 | 100 rows per page | 0.01% |
Worked examples, recomputed
Every number the mechanisms quote for this relationship is recomputed from it, so none of them disagrees with it.
- 10⁶ pages, s = 1, r = 4 → k < 250,000 rows (0.25%)
- r = 1.1 on NVMe → ≈ 909,000 rows (0.9%)
- 8 million rows × 4 = 32,000,000 units against 1,000,000
- row for row with 1.0 and 4.0 → 25%
- 100 rows per page, c_rand/c_seq = 4 → 0.25%
- sequential 1, scattered 5 per MB → crossover at s = 0.2
- delta rows 10× a scanned row → break-even at 10% of the base
Where it appears
Each mechanism states it in its own names. The general symbol each name stands for is shown with it.
- Indexing
When does a separate "where is it?" structure pay for itself, and what does it cost to keep it true?
- Query Planning & Optimization
How does a system choose a plan for a question when the facts that decide the best plan are unknown until the plan has run?
c_seq = · c_rand = · P (pages) =
- Query Planning & Optimization
How does a system choose a plan for a question when the facts that decide the best plan are unknown until the plan has run?
s (selectivity) = · scattered fetch cost = · sequential decode cost =
- Caching
What happens when we deliberately keep a second copy of data that no protocol forces to be correct?
d (delta rows) = · B (base rows) =