So I have this query:
EXPLAIN SELECT SQL_CALC_FOUND_ROWS
u.userid,
u.firstname,
u.lastname,
u.job_title,
u.email,
u.org_id
FROM piltools.users u
WHERE
u.org_id = 'VX3'
AND (
u.firstname LIKE 'Chris%'
OR u.lastname LIKE 'Chris%'
OR CONCAT(u.firstname, ' ', u.lastname) LIKE 'Chris%'
OR u.email LIKE 'Chris%'
)
AND u.firstname !=''
AND u.lastname !=''
AND u.deleted = '0'
There's an index for each of the columns individually and I created a CUSTOM index for deleted,org_id,lastname,firstname,job_title,email,userid especially for this query but when I run explain it says:
id 1
select_type SIMPLE
table u
type ref
possible_keys email,firstname,lastname,org_id,deleted,CUSTOM
key org_id
key_len 17
ref const
rows 113967
extra Using where
Why is it using the individual org_id index instead of my CUSTOM one that has all the fields it needs?
The optimiser tries to asses the time required to process he query with each "possible index", then actually uses the one that it assumes will allow the fastest execution.
Now why it decides not to use your lovingly custom-crafted index cannot be told for sure without knowing the profile of your data but:
an index can only be used to filter on columns in their order of appearance in the declaration. To use the CUSTOM
index, first it must filter records by deleted
(good, this one is par of the WHERE
clause), then by org_id
(also part of your filter), then lastname
, and so on.
most records in your table probably match the condition WHERE deleted = 0
, therefore the benefit of filtering on this field first is considered "low"
then the benefit of filtering on org_id
with CUSTOM
is equal to the benefit from using the index on org_id
only
then the benefit of filtering on condition lastname !=''
is considered "low" because (probably) most of your records do meet this condition
the benefit of filtering on condition lastname LIKE 'Chris%'
is highly mitigated by its being an operand of the OR
operator
same as above for firstname LIKE 'Chris%'
the remaining indexed columns are just not used for filtering
your CUSTOM
index is huge as it mostly includes string columns. The optimiser may assume that the cost of loading this index is too high compared to its possible benefit
You can entice the optimiser to use your index by adding a FORCE INDEX
clause (and not force it as the key word suggests).
But the optimizer usually knows better. If it chooses not to use it, I would trust this decision. You might get better (faster) results with an index on (org_id, deleted)
only, in this order, or perhaps (org_id, deleted, lastname, firstname)
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.