前几篇文章介绍了mysql的底层数据结构和mysql优化的神器explain。后台有些朋友说小强只介绍概念,平时使用仍是一脸懵,强烈要求小强来一篇实战sql优化,通过周末两天的整理和总结,sql优化实战新鲜出炉, 你们平时学习和工做中,遇到的90% 的sql优化都会介绍到,介意篇幅过长,分红3篇文章哈。mysql
CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名', `age` int(20) NOT NULL DEFAULT '0' COMMENT '年龄', `position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位', `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入职时间', PRIMARY KEY (`id`), KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='员工表'; insert into employees(name,age,position,hire_time) values('LiLei', 22, 'manager', NOW()) insert into employees(name,age,position,hire_time) values('HanMeimei', 23, 'dev', NOW()) insert into employees(name,age,position,hire_time) values('Lucy', 23, 'dev', NOW()) 复制代码
索引的字段类型是varchar(n):2字节存储字符串长度,若是是utf-8, 则长度是3n+2web
EXPLAIN select * from employees where name='LiLei'; 复制代码
EXPLAIN select * from employees where name='LiLei' AND age = 22; 复制代码
EXPLAIN select * from employees where name='LiLei' AND age = 22 AND position = 'manager'; 复制代码
若是索引是多列,要最受最左前缀法则。指的是查询从索引的最左前列开始而且不跳过索引中的列。如下两条sql根据最左前缀法则,都不会走索引。sql
EXPLAIN select * from employees where age = 22 AND position='manager'; EXPLAIN select * from employees where position ='manager'; 复制代码
不要在索引列上作任何操做(计算、函数、类型转换),会致使索引失效而转向全表扫描。编程
EXPLAIN select * from employees where name='LiLei'; 复制代码
EXPLAIN select * from employees where left(name, 3)='LiLei'; 复制代码
给hire_time增长一个普通索引:后端
alter table `employees` ADD INDEX `idx_hire_time`(`hire_time`) USING BTREE; EXPLAIN select * from employees where date(hire_time) = '2019-08-25'; 复制代码
还原最初索引状态bash
ALTER TABLE `employees` DROP INDEX `idx_hire_time`;
复制代码
-- EXPLAIN SELECT * FROM employees WHERE name ='LiLei' AND age=22 AND position ='manager'; EXPLAIN SELECT * FROM employees WHERE name ='LiLei' AND age>22 AND position ='manager'; 复制代码
尽可能使用覆盖索引(只访问索引的查询(索引列包含查询列)),减小selelct * 语句。markdown
EXPLAIN SELECT name,age,position FROM employees WHERE name ='LiLei' AND age=22 AND position ='manager'; 复制代码
mysql在使用不等于(! = 或者 <>)的时候没法使用索引会致使全表扫描mysql优化
EXPLAIN SELECT * FROM employees WHERE name !='LiLei' ; 复制代码
is null,is not null也没法使用索引数据结构
EXPLAIN SELECT * FROM employees WHERE name is null;
复制代码
like以通配符开头(‘$abc’)mysql索引失效会变成全表扫描操做机器学习
EXPLAIN SELECT * FROM employees WHERE name LIKE '%Lei'; 复制代码
EXPLAIN SELECT * FROM employees WHERE name ='1000'; EXPLAIN SELECT * FROM employees WHERE name =1000; 复制代码
少用or或in,用它查询时,mysql不必定使用索引,mysql内部优化器会根据索引比例、表大小等多个因素总体评估是否使用索引。
EXPLAIN SELECT * FROM employees WHERE name ='LiLei' or name='HanMeimei'; 复制代码
给年龄添加单值索引
ALTER TABLE `employees`ADD INDEX `idx_age`(`age`) USING BTREE; EXPLAIN select * from employees where age > 1 and age <= 2000; 复制代码
没有走索引缘由:mysql内部优化器会根据检索比例、表大小等多个因素总体评估是否使用索引。 这个例子没有走索引多是由于单次数据量查询过大致使优化器最终选择不走索引。 优化方法:能够将大的范围拆分红多个小范围。
还没关注个人公众号?