MySQL的索引类型包括:
BTREE 索引(目前还不支持函数索引,但是支持前缀索引,即对索引字段的前 N 个字符创建索引)。是InnoDB 存储引擎默认索引类型。
全文本(FULLTEXT)索引(只限于 CHAR、VARCHAR 和 TEXT列);
HASH 索引:只支持MEMORY 存储引擎。
只用于使用=或<=>操作符的等式比较。
优化器不能使用 HASH 索引来加速 ORDER BY 操作。
首先介绍一下关于索引的HINT使用:
use index(index1…)
可能采用该索引,不再考虑其他索引。
事例:
create index idx_emp_job on emp(job);
create index idx_emp_job2 on emp(job,sal);
desc SELECT * FROM emp USE INDEX (idx_emp_job,idx_emp_job2) where job ='SALESMAN';

ignore index (index1…)
忽略考虑该索引
create index idx_emp_job on emp(job);
create index idx_emp_job2 on emp(job,sal);
desc SELECT * FROM emp ignore INDEX (idx_emp_job2) where job ='SALESMAN';

desc SELECT * FROM emp ignore INDEX (idx_emp_job2,idx_emp_job) where job ='SALESMAN';

可以看到,数据库不再考虑该索引的可能性。
force index (index1…)
强制采用该索引,与use index区别在于前者要考虑COST,而后者不考虑COST,强制使用。等价于ORACLE index()。
desc SELECT * FROM emp USE INDEX (idx_emp_job2) where job <>'SALESMAN';

desc SELECT * FROM emp FORCE INDEX (idx_emp_job2) where job <>'SALESMAN';

可以看到,数据库不再考虑成本而直接采用了对应索引访问。
总结一下:索引被使用或不被使用的例子
不被使用的情况:
前%查询
众所周知,数据库对前%查询一般情况均无法使用索引。

即使添加上强制走索引,也无法使用。

换成后%,索引可以使用。

创建前缀索引:
create index idx_emp_job3 on emp(job(4));

可以看到,前缀索引的特性也与普通索引保持一致,只是对索引列的前N个字符存储。
复合索引非前导列查询

不管是考虑还是强制使用,都不走索引。
查询列为OR且不全存在索引时
首先看一下表中现有索引

当条件列为OR关系时,但对应的列不全存在索引,则无法通过索引获得数据。复合索引也不可以。


指定采用索引也无法实现。
隐式转换



可以看到系统显示了警告,由于发生了类型转换,导致无法应用上述索引。
比如下例中也为类型不一致,但没有发生隐式转换,则可以用到索引。

被使用
索引列IS NULL
当索引列为is null查询时,可以使用索引。
间接证明Mysql索引存储空值。

索引列IS NOT NULL
desc select * from emp where job is not null\G
desc select * from emp use index(idx_emp_job) where job is not null\G


可以看到默认采用is not null时,不会自动采用索引访问。
desc select * from emp force index(idx_emp_job) where job is not null\G

可以看到,强制使用索引时,对应SQL是可以采用索引访问的。

查看相关SQL的成本可知,SQL未使用索引的原因,是由于通过索引访问的查询成本高于默认情况下的全表扫描成本,因此造成不自动采用索引访问。
查询列为OR且分别存在索引时

desc select * from emp where job='SALESMAN' or sal='800.00'\G

可以看到,数据库采用了两个索引的MERGE连接。类似于ORACLE的AND-EQUAL用法。




