开发者学堂课程【MySQL 高级应用 - 索引和锁:索引优化7】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/598/detail/8618
索引优化7
目录
一、like以通配符开头 ('%abc... )mysq| 索引失效会变成全表扫描的操作
二、总结
一、like 以通配符开头 ('%abc... )mysq| 索引失效会变成全表扫描的操作
mysql>explain select . name.age.pos FROM staffs WHERE NAME like-
’%July%’ ;
为了简单,可以写成:
mysql> select * FROM staffs WHERE NAME like
’%July%’ ;
1 row in set
(0.00 sec)
mysql> explain select * FROM staffs WHERE NAME like
’%July’ ;
1 row in set
(0.00 sec)
mysql> explain select * FROM staffs WHERE NAME like
’July%’ ;
现在并不是范围之后全失效,三条 sql 除了 % 不同,剩下都相同,也就是说,两边都有 % 有裙带扫描。左边有 % 没有, 右边有% 有。所以一般在写 sql 时,应该把% 写到右边。
现在问题主要在,生产环境中,经常需要两边都写 % ,但是两边都写和只有右边写,查询出的数据,有可能不同。
此时首先根据之前得出的结论:
1. 只有写在最右边才会避免查询失效。并且 like 是查询一个范围。
2. 在生产过程中,必须要写两边百分号
此时就会有一个问题存在:如何解决 like ‘%字符串%’事索引不被使用的方法?
CREATE TABLE ’tbl_ _user’ (
’id' INT(11) NOT NULL AUTO_ INCREMENT,
NAME' VARCHAR(20) DEFAULT NULL,
age INT(11) DEFAULT NULL, .
email VARCHAR(20) DEFAULT NULL,
PRIMARY KEY (id")
) ENGINE=INNODB AUTO_ INCREMENT=1 DEFAULT CHARSET=utf8;
#drop table tbl_ _user
INSERT INTO tbl_ _user(NAME age,email) VALUES('1aa1',21,'b@163.com');
INSERT INTO tbl_ user(NAME,age,email) VALUES('2aa2' ,222,'a@ 163.com');
INSERT INTO tbl _user(NAME,age,email) VALUES('3aa3' ,265, 'c@163.com');
INSERT INTO tbl_ _user(NAME,age,email) VALUES('4aa4' ,21,'d@ 163.com');
此时再创建一张表:
Mysql>show tables:
Tables_in_db0629
Article
Book
Class
Phone
Staffs
Tbl_dept
Tbl_emp
7 rows in set (0.00 sec)
对于 like 两边百分号的原因,比较推荐的方法是覆盖索引,假设
mysql> select * FROM staffs WHERE NAME like
’%aaa%’ ;
4 row in set
(0.00 sec)
mysql> select * FROM staffs WHERE NAME like
’aaa’ ;
Empty set
(0.00 sec)
mysql> select * FROM staffs WHERE NAME like
’%aaa’ ;
Empty set
(0.00 sec)
现在在建立索引之前,
Mysql> show index from tb1_user
1 row in set (0.00 sec)
#before index
EXPLAIN select id FROM tbl_ _user WHERE NAME LIKE '%aa%';
EXPLAIN select NAME FROM tbl_ user WHERE NAME LIKE '%aa%';
EXPLAIN select age FROM tbl_ user WHERE NAME LIKE '%aa%';
EXPLAIN select id,NAME FROM tbl user WHERE NAME LIKE '%aa%;
为了节省时间,将以上4条一起复制进来,查看结果:
此时,单独用 id 没有索引,单独 name 和 age 也是一样, 现在继续执行:
EXPLAIN select NAME,age,ROM tbl_ _user WHERE NAME LIKE '%aa%';
EXPLAIN select NAME,age, FROM tbl_ _user WHERE NAME LIKE '%aa%';
以上是没有索引的状态,字段从 * 到所有字段,单独的字段,都没有显示。如果必须要用两边 %,先来进行逐步分析:
没建索引之前,全表扫描,索引失效;
此时需要完成,两边百分号,索引不能失效;
所以需要用覆盖索引来保证避免全表扫描;
建完索引之后,如果不写 * ,也可以从主键索取信息;
单独建立索引,只查询一个,也会得到信息,索引没有失效;
*代表所有字段,在部分查询的时候,索引会失效;
如果查询的内容多,而查询的范围少,此时索引也会失效;
所以,如果必须要两边都写 % ,此时需要调用覆盖索引。
二、总结
1.Id 永远自带主键索引
2.Name和 age 如果只写右边 % ,查询不出结果,两边都写,可以查询出4条
3.如果又想两边都写% ,又想查询出结果而索引不失效,就调用覆盖索引。覆盖索引是指:建立的索引和查询的字段,个数和顺序最好完全一致。此时单独 id 可以使用,* 或者多元素,不可使用。