Range Optimizer

Range optimizer is a part of MariaDB (and MySQL) optimizer that takes as input

  • the table and index definition(s)

  • the WHERE condition (or ON expression if the table is inner in an outer join)

and constructs list of ranges one can scan in an index to read the rows that match the WHERE condition, or a superset of it. It can also construct an "index_merge" plan, where one needs ranges from two or more indexes to compute a union (formed from multiple condition disjunctions) and/or intersection (formed from multiple condition conjunctions).

Basic example

Consider a table

CREATE TABLE t1 (
  key1 INT,
  key2 VARCHAR(100),
  ...
  INDEX(key1),
  INDEX(key2)
);

and query

-- Turn on optimizer trace so we can see the ranges:
SET optimizer_trace=1; 
EXPLAIN SELECT * FROM t1 WHERE key1<10 AND key2='foo';
SELECT * FROM information_schema.optimizer_trace\G

This shows the ranges that the optimizer was able to infer:

Ranges are non-overlapping

Range optimizer produces a list of ranges without overlaps. Consider this WHERE clause where conditions do have overlaps:

We get

Ranges for multi-part indexes

Let's consider an index with multiple key parts. (note: due to Extended Keys optimization, an index may have more key parts than you've explicitly defined)

Range optimizer will generate a finite set of ranges over lexicographical ordering over (keypart1, keypart2, ...).

Example:

gives

Compare with a similar query:

this will generate just one bigger range:

which includes for example rows like (keypart1,keypart2)=(1,zzz). One could argue that the optimizer could be able to figure out that for condition keypart1 between 1 and 3 the only possible values are 1, 2, 3 but this is not implemented.

Not all comparisons produce ranges

Note that some keypart comparisons produce multi-part ranges while some do not. The governing rule is the same: the conditions together must produce an interval (or a finite number of intervals) in lexicographic order in the index.

Some examples:

can use the second keypart:

but the interval will still include rows like (keypart1, keypart2) = (8, 'zzzz')

Non-inclusive bound on keypart1 prevents any use of keypart2. For

we get

Non-agreeing comparison (less than and greater than) do not produce a multi-part range:

gives

A "Hole" in keyparts means higher keypart cannot be used.

gives

Combinatorial blow-ups

For multi-part keys, range analyzer can produce ranges that are "tight", that is, they only include rows that will match the WHERE condition. On the other hand, some SQL constructs can produce very large (combinatorial) amounts of ranges. Consider a query

two IN-lists produce 3*4 =12 ranges:

if one adds and keypart3 IN (1,2,3,4,5), the amount of ranges will be 345=60 and so forth. See optimizer_max_sel_arg_weight on how to combat this.

This page is licensed: CC BY-SA / Gnu FDL

Last updated

Was this helpful?