Imagine I have a (huge) table like so:
category type
-------- ----
foo EC22
foo EC00
bar EC00
bar EDC0
... ...
The first two characters in type
have a special meaning and I'm only interested in those for SELECT
purposes. I want to use a composite index with a prefix on type
like so: category, type(2)
Now when I do:
EXPLAIN SELECT category, type FROM table
WHERE category = 'foo'
AND LEFT(type,2) = 'EC'
... it tells me MySQL is Using index condition;
(meaning rows are read to doublecheck the index).
I want to use everything that has an index value of EC
and continue with the rest of my index-only scan. E.g. EXPLAIN
telling me Using index;
(without condition
). There is no need to double check the actual value of this field, because I'm only looking at the first two characters. Is it possible to achieve or force this?
I can SET optimizer_switch='index_condition_pushdown=off';
and then EXPLAIN
changes from Using index lookup;
to Using where;
and it's about 15% faster. I guess I'm not entirely sure what's going on here and how I can see my query is done using indices alone.
When EXPLAIN
shows "Using index", that means that the index is a covering index for the query. That is, the query can be satisfied entirely from the index blocks, without requiring any lookups of rows in the underlying table blocks.
Look at your query again. And notice that it's returning the type
column (the expression in the SELECT list.) That's the whole column. And that whole column is not available in the index.
So that index can't be a covering index for the query, so MySQL isn't ever going to show 'Using index' in the EXPLAIN output (with that query and that index.)
Since it's not a covering index for the query, MySQL will have to do the lookup to the underlying data page to get the value of the column so it can be returned.
Now as far as whether the index is being used to check the condition LEFT(type,2) = 'EC'
, we'd need to check the key_len
in the EXPLAIN output.
We can compare the key_len
in the EXPLAIN when there is no condition on the type
column vs when there is a condition. I'd also test with a condition such as type LIKE 'EC%'
.
I'd compare key_len
from the EXPLAIN for all of these:
SELECT category, type FROM huge_table WHERE category = 'bar' ;
SELECT category, type FROM huge_table WHERE category = 'bar' AND type LIKE 'E%' ;
SELECT category, type FROM huge_table WHERE category = 'bar' AND type LIKE 'EC%' ;
SELECT category, type FROM huge_table WHERE category = 'bar' AND LEFT(type,1) = 'E' ;
SELECT category, type FROM huge_table WHERE category = 'bar' AND LEFT(type,2) = 'EC' ;
If key_len
is the same (i.e. the length of just the category
column) in all those cases, then that suggests that MySQL isn't making use the index to check the LEFT(type,2) =
condition.
And you would be correct. MySQL is visiting the underlying data page before it checks the condition.
But if key_len
is longer in some of those cases, that suggests that MySQL is checking the condition from the index, before it does the lookup of the row.
You might also get an EXPLAIN for a query that doesn't include the type
column in the SELECT list.