前几篇文章介绍了mysql的底层数据结构和mysql优化的神器explain。后台有些朋友说小强只介绍概念,平时使用还是一脸懵,强烈要求小强来一篇实战sql优化,经过周末两天的整理和总结,sql优化实战新鲜出炉, 大家平时学习和工作中,遇到的90% 的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';

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

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

还原最初索引状态

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



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

覆盖索引

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

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

条件判断

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

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

空值判断

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

EXPLAIN SELECT * FROM employees WHERE name is null;

like

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;



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

or&in少使用

少用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内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。

这个例子没有走索引可能是因为单次数据量查询过大导致优化器最终选择不走索引。

优化方法:可以将大的范围拆分成多个小范围。

还没关注我的公众号?

  • 扫文末二维码关注公众号【小强的进阶之路】可领取如下:
  • 学习资料: 1T视频教程:涵盖Javaweb前后端教学视频、机器学习/人工智能教学视频、Linux系统教程视频、雅思考试视频教程;
  • 100多本书:包含C/C++、Java、Python三门编程语言的经典必看图书、LeetCode题解大全;
  • 软件工具:几乎包括你在编程道路上的可能会用到的大部分软件;
  • 项目源码:20个JavaWeb项目源码。

工作中遇到的99%SQL优化,这里都能给你解决方案的更多相关文章

  1. 工作中遇到的99%SQL优化,这里都能给你解决方案(二)

    -- 示例表 CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT NULL ...

  2. 工作中遇到的99%SQL优化,这里都能给你解决方案(三)

    -- 示例表 CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT NULL ...

  3. 收集一些工作中常用的经典SQL语句

    作为一枚程序员来说和数据库打交道是不可避免的,现收集一下工作中常用的SQL语句,希望能给大家带来一些帮助,当然不全面,欢迎补充! 1.执行插入语句,获取自动生成的递增的ID值 INSERT INTO ...

  4. 在工作中常用到的SQL

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近在公司做了几张报表,还记得刚开始要做报表的时候都 ...

  5. 工作中常用到的sql命令!!!

    一.mysql数据库日常操作.     1.启动mysql:/etc/init.d/mysql start (前面为mysql的安装路径)     2.重启mysql:  /etc/init.d/my ...

  6. 工作中遇到的一道SQL应用题

    登录日志表 CREATE TABLE [dbo].[LoginLog]([Seq] [int] NOT NULL IDENTITY(1, 1),  --Seq[UserId] [varchar] (2 ...

  7. 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)

    查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...

  8. 《高性能SQL调优精要与案例解析》一书谈SQL调优(SQL TUNING或SQL优化)学习

    <高性能SQL调优精要与案例解析>一书上市发售以来,很多热心读者就该书内容及一些具体问题提出了疑问,因读者众多外加本人日常工作的繁忙 ,在这里就SQL调优学习进行讨论并对热点问题统一作答. ...

  9. Oracle SQl优化总结

    对数据库技术的热爱是我唯一的安慰,毕竟这是自己喜欢的事情,还可以做下去. 因为客户项目的需要,我又开始接触Oracle,大部分工作在工作流的优化和业务数据的排查上.为了更好的做这份工作,我有参考过or ...

随机推荐

  1. spark 源码分析之九--Spark RPC剖析之StreamManager和RpcHandler

    StreamManager StreamManager类说明 StreamManager 官方说明如下: The StreamManager is used to fetch individual c ...

  2. Mysql 学校信息管理系统

    1.创建数据库语句: #创建数据库 CREATE DATABASE `schoolDB`; USE `schoolDB`; #创建学生表 CREATE TABLE `student`( `sid` I ...

  3. On The Way—Step 1 :python入门之Python的历程

    1.python的历史 2004 Django框架 python2 和 python3的区别 python2 源码不统一 有重复功能代码 python3 源码统一 没有重复功能代码 Python的发展 ...

  4. Java学习-内存划分及内存的调用关系

    一.JAVA内存划分 JAVA的内存可以划分为五个部分:堆.栈.方法区.本地方法区和寄存器. 堆(Heap):凡是new出来的东西都在堆中 如: integer = new Integer(2) // ...

  5. 【iOS】The filename 未命名.ipa in the package contains an invalid character(s)

    提交 APP 到苹果官网审核时遇到了这个问题,如图: 其实就是不支持中文,随便换个英文名就行了. 参考:http://blog.csdn.net/u011439689/article/details/ ...

  6. ZK安装、ZK配置、ZK集群部署

    今天心血来潮,想搞一下zookeeper集群.具体步骤记录下吧~嘻嘻

  7. 使用request获取访问者的真实IP

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  8. c#小灶——注释和代码规范

    为什么要写注释? 早上我写完了代码,我和我的朋友们都能看懂,到了晚上,我还能看懂,一周后,就只有上帝能看懂了…… 将来我们写的代码量是很大的,代码又不像我们自然语言这么好理解,可能过段时间我们就不认识 ...

  9. HTML 第4章初始CSS3

    什么是CSS? CSS全称为层叠样式表,通常又称为风格样式表. 引用CSS样式: 语法: <h1 styske="color:red;">style属性的应用</ ...

  10. Java Lambda表达式forEach无法跳出循环的解决思路

    Java Lambda表达式forEach无法跳出循环的解决思路 如果你使用过forEach方法来遍历集合,你会发现在lambda表达式中的return并不会终止循环,这是由于lambda的底层实现导 ...