为什么MySQL不使用我为它制作的索引?

时间:2013-06-19 18:07:07

标签: mysql indexing

所以我有这个问题:

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'

每个列都有一个索引,我为删除的org_id,lastname,firstname,job_title,email,userid创建了一个CUSTOM索引,特别是对于这个查询,但是当我运行解释它时说:

id 1

select_type SIMPLE

输入参考

possible_keys 电子邮件,名字,姓氏,org_id,已删除,CUSTOM

org_id

key_len 17

参考 const

113967

额外使用

为什么它使用单独的org_id索引而不是我的CUSTOM索引包含它需要的所有字段?

1 个答案:

答案 0 :(得分:1)

优化器会尝试使用每个“可能的索引”来评估处理查询所需的时间,然后实际使用它假定允许最快执行的那个。

现在,为什么它决定不使用您精心定制的索引,如果不知道您的数据配置文件就无法确定,但是:

  • 索引只能用于在声明中按其出现顺序过滤列。要使用CUSTOM索引,首先它必须按deleted过滤记录(好,这个是WHERE子句的标准),然后是org_id(也是你的一部分)过滤器),然后是lastname,依此类推。

  • 表中的大多数记录可能与条件WHERE deleted = 0匹配,因此首先对此字段进行过滤的好处被视为“低”

  • 那么使用org_id过滤CUSTOM的好处等于仅使用org_id上的索引带来的好处

  • 然后在条件lastname !=''上过滤的好处被认为是“低”,因为(可能)您的大多数记录都符合此条件

  • 条件lastname LIKE 'Chris%'的过滤优势因其作为OR运算符

  • 的操作数而得到高度缓解
  • firstname LIKE 'Chris%'

  • 相同
  • 其余的索引列仅用于过滤

  • 您的CUSTOM索引很大,因为它主要包含字符串列。优化者可能会认为加载此指数的成本与其可能的收益相比过高

您可以通过添加FORCE INDEX子句来诱使优化器使用您的索引(而不是强制,如关键词所示)。

但优化器通常知道的更好。如果它选择不使用它,我会相信这个决定。只有(org_id, deleted)上的索引,按此顺序,或者(org_id, deleted, lastname, firstname),您可能会获得更好(更快)的结果。