For WHERE primary_key < 10 AND key_col1 = 20
, provide
INDEX(key_col1, primary_key)
in that order. Discussion:
- Put
=
columns first in the index; one 'range' last.
- Index merge might be usable without the above 'composite' index, but it will not be as efficient.
- It would be specifically "index merge intersect" (as opposed to "... union").
- I have yet to find a case where index merge intersect is faster than a suitable composite index.
How would merge work?
- Gather a list of PKs satisfying
primary_key < 10
- Gather a list of PKs satisfying
key_col1 = 20
- "merge" those two lists ("AND").
- Use the PKs to look up the row(s) (
SELECT *
).
How would the composite key work?
- Using the index's BTree, locate the first 'row' in the index with
key_col1 = 20
; it will have the smallest primary_key
.
- Reach into the table to get
SELECT *
using the PK.
- Move on to the next row in the index.
- Repeat steps 2, 3 until hitting
10
.
Without the composite index, probably this is what the optimizer will do:
- Start at the beginning of the table (no index being used)
- Ignore row if
key_col1 = 20
is false; else deliver row
- repeat until
primary_key < 10
EXPLAIN SELECT ...
will tell you which method it chose.
As for index merge union...
- It is only(?) used with
OR
.
- It is rarely used.
- Sometimes reformulating the query to use
UNION
instead of OR
is a better option.