简体   繁体   中英

Why isn't MySQL using the index I made for it?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM