一、索引失效(应该避免)

  1. CREATE TABLE staffs(
  2. id INT PRIMARY KEY AUTO_INCREMENT,
  3. NAME VARCHAR(24) NOT NULL DEFAULT '' COMMENT '姓名',
  4. age INT NOT NULL DEFAULT 0 COMMENT '年龄',
  5. pos VARCHAR(20) NOT NULL DEFAULT '' COMMENT '职位',
  6. add_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间'
  7. )CHARSET utf8 COMMENT '员工记录表';
  8. INSERT INTO staffs(NAME,age,pos,add_time) VALUES('z3',22,'manager',NOW());
  9. INSERT INTO staffs(NAME,age,pos,add_time) VALUES('July',23,'dev',NOW());
  10. INSERT INTO staffs(NAME,age,pos,add_time) VALUES('2000',23,'dev',NOW());
  11. SELECT * FROM staffs; h
  12. ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(name, age, pos); # 新建复合索引
  13. show index from staffs

(2)最佳左前缀法则

  1. explain select * from staffs WHERE NAME='July'

image.png

  1. explain select * from staffs WHERE NAME='July' and age = 25 and pos='dev'

image.png

  1. explain select * from staffs WHERE age = 25 and pos='dev'

image.png
全表扫描并且没有用到索引

建立的索引NameAgePos,如果前面没有了Name,会发现没有用到索引。

这里违背了最佳左前缀法则,如果索引了多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始并且不跳过索引中的列

  1. explain select * from staffs WHERE NAME='July' and pos='dev'

image.png
这个跳过了中间列了,key_len 变小了,rows 应该为2

(1)全值匹配我最爱

(3)不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。

  1. EXPLAIN SELECT * FROM staffs WHERE NAME = 'July'

image.png

  1. EXPLAIN SELECT * FROM staffs WHERE LEFT(NAME,4) = 'July'

image.png

(4)存储引擎不能使用索引中范围右边的列

image.png
https://blog.csdn.net/m0_45406092/article/details/112196476

(5)尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *

image.png

(6)mysql 在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描

  1. EXPLAIN SELECT * FROM staffs WHERE NAME != 'July'

image.png

(7)is null , is not null 无法使用索引

  1. EXPLAIN SELECT * FROM staffs WHERE NAME is null

image.png

  1. EXPLAIN SELECT * FROM staffs WHERE NAME is not null

image.png

(8) like 以通配符开头(’%abc..’)mysql索引失效会变成全表扫描的操作

  1. E--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------XPLAIN select * from staffs WHERE name like '%July%'

image.png

  1. EXPLAIN select * from staffs WHERE name like '%July'

image.png

  1. EXPLAIN select * from staffs WHERE name like 'July%'

image.png
可以看到右边的百分号可以是range。

问题解决like ‘%字符串%’时索引不被使用的方法?

  1. CREATE TABLE `tbl_user` (
  2. `id` INT(11) NOT NULL AUTO_INCREMENT,
  3. `NAME` VARCHAR(20) DEFAULT NULL,
  4. `age` INT(11) DEFAULT NULL,
  5. email VARCHAR(20) DEFAULT NULL,
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  8. INSERT INTO tbl_user(NAME,age,email) VALUES('1aa1',21,'b@163.com');
  9. INSERT INTO tbl_user(NAME,age,email) VALUES('2aa2',222,'a@163.com');
  10. INSERT INTO tbl_user(NAME,age,email) VALUES('3aa3',265,'c@163.com');
  11. INSERT INTO tbl_user(NAME,age,email) VALUES('4aa4',21,'d@163.com');
  12. INSERT INTO tbl_user(NAME,age,email) VALUES('aa',121,'e@163.com');

like ‘%abc%’ type 类型会变成 all
like ‘abc%’ type 类型为 range ,算是范围,可以使用索引
解决like ‘%字符串%’时索引不被使用的方法:使用覆盖索引

(9)字符串不加单引号会导致索引失效

image.png
image.png

(10)少用or,用它来连接时会索引失效

(11)小总结

image.png

————————————————• 索引列上使用函数

索引失效:

• where id +1=4
• 字符串不加引号, 出现隐式转换
• 索引类型为varchar时,使用int类型查询索引失效,使用string类型查询才能生效
• 索引字段是int时,使用Int类型查询和string类型都生效
• like 条件中 前面加 %
• 负向查询
• not like 不可以
• or条件查询,所有的字段都简历索引才能命中索引