sql是否包含多个字符串_工作中遇到的99%SQL优化,这里都能给你解决方案

点击上方“小强的进阶之路”,选择“星标”公众号

重磅干货,第一时间送达!

e58af4f800c1d0996748e44e6f72f15a.png

预计阅读时间:8分钟

前几篇文章介绍了mysql的底层数据结构和mysql优化的神器explain。

BAT大厂都会问的MySQL底层数据结构

一线互联网公司必问的MySql优化神器

后台有些朋友说小强只介绍概念,平时使用还是一脸懵,强烈要求小强来一篇实战sql优化,经过周末两天的整理和总结,sql优化实战新鲜出炉, 大家平时学习和工作中,遇到的99% 的sql优化都会介绍到,介于篇幅过长,分成3篇文章哈。

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+2

EXPLAIN select * from employees where name='LiLei';

a1a92e22fb071d51d935058d7064fdc2.png

EXPLAIN select * from employees where name='LiLei' AND age = 22;

fce1a0f573ddfd3e1ef9e932fa33374e.png

EXPLAIN select * from employees where name='LiLei' AND age = 22 AND position = 'manager';

最左前缀法则

如果索引是多列,要最受最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。以下三条sql根据最左前缀法则,都不会走索引。

EXPLAIN select * from employees where age = 22 AND position='manager';

EXPLAIN select * from employees where position ='manager';

EXPLAIN select * from employees where age=17;

be8795d3b073c89b825186747f766678.png

索引失效

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

EXPLAIN select * from employees where name='LiLei';

ac3d97345a66dc170a7d42d3c2755c01.png

EXPLAIN select * from employees where left(name, 3)='LiLei';

8fe20b211932a81158ee3f49b5c99827.png

给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';

c95e8c5b4507155813d1592e9399e68a.png

还原最初索引状态

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';

534a21dfeda51d6cbc8f8784b3fe2cd7.png看到key_len这个索引长度是78, 也就是只使用到了前两个字段name和age,postition没有使用到索引的。

覆盖索引

尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少selelct * 语句。

EXPLAIN SELECT name,age,position FROM employees WHERE name ='LiLei' AND age=22 AND position ='manager';

aa3d16189f4d2e84de41b61b0986b17b.png

条件判断

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

EXPLAIN SELECT * FROM employees WHERE name !='LiLei' ;

64587928fe067a948a6cdd1bff6501ba.png

空值判断

is null,is not null也无法使用索引

EXPLAIN SELECT * FROM employees WHERE name is null;

80108a5d628222408aa59dcb5580a3da.png

like

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

EXPLAIN SELECT * FROM employees WHERE name LIKE '%Lei';

243ee6b7e659018915f6d1d2c18b9c0c.png

字符串不加单引号索引失效

EXPLAIN SELECT * FROM employees WHERE name ='1000';

EXPLAIN SELECT * FROM employees WHERE name =1000;

fcc528381af23d6050b3cfef8ce6fdf4.png不加单引号的字符串,mysql底层会使用cust函数将其转换为字符串,此时索引失效。

or&in少使用

少用or或in,用它查询时,mysql不一定使用索引,mysql内部优化器会根据索引比例、表大小等多个因素整体评估是否使用索引。

EXPLAIN SELECT * FROM employees WHERE name ='LiLei' or name='HanMeimei';

682829e3eaca4f16712a901b326840b2.png

范围查询优化

给年龄添加单值索引

ALTER TABLE `employees`ADD INDEX `idx_age`(`age`) USING BTREE;

EXPLAIN select * from employees where age > 1 and age <= 2000;

a9dfe01b2abf9e1c8a855b9e27c94416.png

没有走索引原因:mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。这个例子没有走索引可能是因为单次数据量查询过大导致优化器最终选择不走索引。优化方法:可以将大的范围拆分成多个小范围。

End

关注【小强的进阶之路】技术公众号:

  • 回复“1”进大型内推群!

  • 回复“2”免费获取海量开发学习资料!

  • 回复“3”加入知识星球,和大牛一起学习!

  • 近期热文:

  • 比Hive快500倍!大数据实时分析领域的黑马

  • 《从0到1学习Netty》-遇见Netty

  • 互联网JAVA面试常问问题(七)- 带你走入AQS同步器源码

👇👇👇戳二维码关注小强哦~👇👇👇

2ec076685500369f1c760ecc34317be8.png

最新干货,我在看❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值