备注:因为mysql优化器的缘故,与索引顺序不一致,也会触发索引,但实际项目中尽量顺序一致。

5、联合索引,但其中一个条件是 >

6、联合索引,order by

where和order by一起使用时,不要跨索引列使用。

三、单表sql优化


1、删除student表中的联合索引。

2、添加索引


alter table student add index student_union_index(name,age,sex);

优化一点,但效果不是很好,因为type是index类型,extra中依然存在using where。

3、更改索引顺序

因为sql的编写过程


select distinct ... from ... join ... on ... where ... group by ... having ... order by ... limit ...

解析过程


from ... on ... join ... where ... group by ... having ... select distinct ... order by ... limit ...

因此我怀疑是联合索引建的顺序问题,导致触发索引的效果不好。are you sure?试一下就知道了。


alter table student add index student_union_index2(age,sex,name);

删除旧的不用的索引:


drop index student_union_index on student

索引改名


ALTER TABLE student RENAME INDEX student_union_index2 TO student_union_index

更改索引顺序之后,发现type级别发生了变化,由index变为了range。

range:只检索给定范围的行,使用一个索引来选择行。

备注:in会导致索引失效,所以触发using where,进而导致回表查询。

4、去掉in

ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取;

index 提升为ref了,优化到此结束。

5、小结

  1. 保持索引的定义和使用顺序一致性;

  2. 索引需要逐步优化,不要总想着一口吃成胖子;

  3. 将含in的范围查询,放到where条件的最后,防止索引失效;

四、双表sql优化


1、建表语句


CREATE TABLE `student` (`id` int(10) NOT NULL,`name` varchar(20) NOT NULL,`age` int(10) NOT NULL,`sex` int(11) DEFAULT NULL,`address` varchar(100) DEFAULT NULL,`phone` varchar(100) DEFAULT NULL,`create_time` timestamp NULL DEFAULT NULL,`update_time` timestamp NULL DEFAULT NULL,`deleted` int(11) DEFAULT NULL,`teacher_id` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE teacher (

id int(11) DEFAULT NULL,

name varchar(100) DEFAULT NULL,

course varchar(100) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

### 2、左连接查询 

explain select s.name,t.name from student s left join teacher t on s.teacher_id = t.id where t.course = ‘数学’

![](https://img-blog.csdnimg.cn/20210710142808178.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)上一篇介绍过,联合查询时,小表驱动大表。小表也称为驱动表。其实就相当于双重for循环,小表就是外循环,第二张表(大表)就是内循环。虽然最终的循环结果都是一样的,都是循环一样的次数,但是对于双重循环来说,一般建议将数据量小的循环放外层,数据量大的放内层,这是编程语言的优化原则。再次代码测试:student数据:四条![](https://img-blog.csdnimg.cn/20210710143804318.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)teacher数据:三条![](https://img-blog.csdnimg.cn/20210710143900257.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)按照理论分析,teacher应该为驱动表。![](https://img-blog.csdnimg.cn/20210710143633450.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)sql语句应该改为:

explain select teacher.name,student.name from teacher left join student on teacher.id = student.id where teacher.course = ‘数学’

优化一般是需要索引的,那么此时,索引应该怎么加呢?往哪个表上加索引?索引的基本理念是:索引要建在经常使用的字段上。由on teacher.id = student.id可知,teacher表的id字段使用较为频繁。left join on,一般给左表加索引;因为是驱动表嘛。![](https://img-blog.csdnimg.cn/2021071014465582.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)

alter table teacher add index teacher_index(id);

alter table teacher add index teacher_course(course);

![](https://img-blog.csdnimg.cn/20210710150451965.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)备注:如果extra中出现using join buffer,表明mysql底层觉得sql写的太差了,mysql加了个缓存,进行优化了。### 3、小结1.  小表驱动大表2.  索引建立在经常查询的字段上3.  sql优化,是一种概率层面的优化,是否实际使用了我们的优化,需要通过explain推测。五、避免索引失效的一些原则-------------1、复合索引,不要跨列或无序使用(最佳左前缀);2、符合索引,尽量使用全索引匹配;3、不要在索引上进行任何操作,例如对索引进行(计算、函数、类型转换),索引失效;4、复合索引不能使用不等于(!=或<>)或 is null(is not null),否则索引失效;5、尽量使用覆盖索引(using index);6、like尽量以常量开头,不要以%开头,否则索引失效;如果必须使用%name%进行查询,可以使用覆盖索引挽救,不用回表查询时可以触发索引;7、尽量不要使用类型转换,否则索引失效;8、尽量不要使用or,否则索引失效;六、一些其他的优化方法-----------### 1、exist和in

select name,age from student exist/in (子查询);

如果主查询的数据集大,则使用in;如果子查询的数据集大,则使用exist;### 2、order by 优化using filesort有两种算法:双路排序、双路排序(根据IO的次数)MySQL4.1之前,默认使用双路排序;双路:扫描两次磁盘(①从磁盘读取排序字段,对排序字段进行排序;②获取其它字段)。MySQL4.1之后,默认使用单路排序;单路:只读取一次(全部字段),在buffer中进行排序。但单路排序会有一定的隐患(不一定真的是只有一次IO,有可能多次IO)。注意:单路排序会比双路排序占用更多的buffer。单路排序时,如果数据量较大,可以调大buffer的容量大小。

set max_length_for_sort_data = 1024;单位是字节byte。

如果max\_length\_for\_sort\_data值太低,MySQL底层会自动将单路切换到双路。太低指的是列的总大小超过了max\_length\_for\_sort\_data定义的字节数。提高order by查询的策略:1.  选择使用单路或双路,调整buffer的容量大小;2.  避免select \* from student;(① MySQL底层需要对\*进行翻译,消耗性能;② \*永远不会触发索引覆盖 using index);3.  符合索引不要跨列使用,避免using filesort;4.  保证全部的排序字段,排序的一致性(都是升序或降序);七、sql顺序 -> 慢日志查询----------------慢查询日志就是MySQL提供的一种日志记录,用于记录MySQL响应时间超过阈值的SQL语句(long\_query\_time,默认10秒) ;慢日志默认是关闭的,开发调优时打开,最终部署时关闭。### 1、慢查询日志(1)检查是否开启了慢查询日志:

show variables like ‘%slow_query_log%’

![](https://img-blog.csdnimg.cn/20210710233419230.png)(2)临时开启:

set global slow_query_log = 1;

(3)重启MySQL: 

service mysql restart;

(4)永久开启:/etc/my.cnf中追加配置:放到\[mysqld\]下:

slow_query_log=1

slow_query_log_file=/var/lib/mysql/localhost-slow.log

### 2、阈值(1)查看默认阈值:

show variables like ‘%long_query_time%’

(2)临时修改默认阈值:

set global long_query_time = 5;

(3)永久修改默认阈值:/etc/my.cnf中追加配置:放到\[mysqld\]下:long\_query\_time = 5;(4)MySQL中的sleep:

select sleep(5);

(5)查看执行时间超过阈值的sql:

show global status like ‘%slow_queries%’;

八、慢查询日志 --> mysqldumpslow工具---------------------------### 1、mysqldumpslow工具慢查询的sql被记录在日志中,可以通过日志查看具体的慢sql。

cat /var/lib/mysql/localhost-slow.log

通过mysqldumpslow工具查看慢sql,可以通过一些过滤条件,快速查出需要定位的慢sql。

mysqldumpslow --help

参数简要介绍:s:排序方式r:逆序l:锁定时间g:正则匹配模式### 2、查询不同条件下的慢sql(1)返回记录最多的3个SQL

mysqldumpslow -s r -t 3 /var/lib/mysql/localhost-slow.log

(2)获取访问次数最多的3个SQL

mysqldumpslow -s c -t 3 /var/lib/mysql/localhost-slow.log

(3)按时间排序,前10条包含left join查询语句的SQL

mysqldumpslow -s t -t 10 -g “left join” /var/lib/mysql/localhost-slow.log

九、分析海量数据--------### 1、show profiles打开此功能:set profiling = on;show profiles会记录所有profileing打来之后,全部SQL查询语句所花费的时间。缺点是不够精确,确定不了是执行哪部分所消耗的时间,比如CPU、IO。### 2、精确分析,sql诊断show profile all for query  上一步查询到的query\_id。### 3、全局查询日志show variables like '%general\_log%'开启全局日志:set global general\_log = 1;set global log\_output = table;十、锁机制详解-------### 1、操作分类读写:对同一个数据,多个读操作可以同时进行,互不干扰。写锁:如果当前写操作没有完毕,则无法进行其它的读写操作。### 2、操作范围表锁:一次性对一张表整体加锁。如MyISAM存储引擎使用表锁,开销小、加锁快、无死锁;但锁的范围大,容易发生冲突、并发度低。行锁:一次性对一条数据加锁。如InnoDB存储引擎使用的就是行锁,开销大、加锁慢、容易出现死锁;锁的范围较小,不易发生锁冲突,并发度高(很小概率发生高并发问题:脏读、幻读、不可重复读)lock table 表1 read/write,表2 read/write,...查看加锁的表:show open tables;### 3、加读锁,代码实例

会话0:

lock table student read;

select * from student; --查,可以

delete from student where id = 1;–增删改,不可以

select * from user; --查,不可以

delete from user where id = 1;–增删改,不可以

如果某一个会话对A表加了read锁,则该会话可以对A表进行读操作、不能进行写操作。即如果给A表加了读锁,则当前会话只能对A表进行读操作,其它表都不能操作

会话1:

select * from student; --查,可以

delete from student where id = 1;–增删改,会“等待”会话0将锁释放

会话1:

select * from user; --查,可以

delete from user where id = 1;–增删改,可以

会话0给A表加了锁,其它会话的操作①可以对其它表进行读写操作②对A表:读可以,写需要等待释放锁。### 4、加写锁

会话0:

lock table student write;

当前会话可以对加了写锁的表,可以进行任何增删改查操作;但是不能操作其它表;其它会话:对会话0中对加写锁的表,可以进行增删改查的前提是:等待会话0释放写锁。### 5、MyISAM表级锁的锁模式MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改前,会自动给涉及的表加写锁。所以对MyISAM表进行操作,会有如下情况发生:(1)对MyISAM表的读操作(加读锁),不会阻塞其它会话(进程)对同一表的读请求。但会阻塞对同一表的写操作。只有当读锁释放后,才会执行其它进程的写操作。(2)对MyISAM表的写操作(加写锁),会阻塞其它会话(进程)对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。### 6、MyISAM分析表锁定查看哪些表加了锁:show open tables;1代表被加了锁分析表锁定的严重程度:show status like 'table%';![](https://img-blog.csdnimg.cn/20210711203541856.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)Table\_locks\_immediate:可能获取到的锁数Table\_locks\_waited:需要等待的表锁数(该值越大,说明存在越大的锁竞争)一般建议:Table\_locks\_immediate/Table\_locks\_waited > 5000,建议采用InnoDB引擎,否则采用MyISAM引擎。### 7、InnoDB分析表锁定为了研究行锁,暂时将自动commit关闭,set autocommit = 0;show status like '%innodb\_row\_lock%';![](https://img-blog.csdnimg.cn/20210711204735810.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b3J1aV9qYXZh,size_16,color_FFFFFF,t_70)Innodb\_row\_lock\_current\_waits:当前正在等待锁的数量  Innodb\_row\_lock\_time:等待总时长。从系统启动到现在一共等待的时间  Innodb\_row\_lock\_time\_avg:平均等待时长。从系统启动到现在一共等待的时间  Innodb\_row\_lock\_time\_max:最大等待时长。从系统启动到现在一共等待的时间  Innodb\_row\_lock\_waits:等待次数。从系统启动到现在一共等待的时间### 8、加行锁代码实例(1)查询student

select id,name,age from student

Java基础语法教学视频,MySql知识体系总结(SQL优化篇相关推荐

  1. MySql基础知识总结(SQL优化篇)

  2. Java基础语法知识你真的都会吗?

    第一阶段 JAVA基础知识 第二章 Java基础语法知识 在我们开始讲解程序之前,命名规范是我们不得不提的一个话题,虽说命名本应该是自由的,但是仍然有一定的"潜规则",通过你对命名 ...

  3. 打怪升级之小白的大数据之旅(一)<Java基础语法之Java的身世之谜>

    打怪升级之小白的大数据之旅(一) Java基础语法之Java的身世之谜 打怪升级之小白的大数据之旅(一) 前言 一.学习大数据之前 二.Java基础 what? why? how? 总结 前言 做了几 ...

  4. Java基础语法(一)——初识Java

    文章目录 一.Java语言概述 1.Java是什么 2.Java 的流行性 3.Java 的特性 (1) 简单性 (2)面向对象 (3) 分布式(微服务) (4) 健壮性 (5) 安全性 (6) 可移 ...

  5. JavaSE_第2章 Java基础语法

    JavaSE_第2章 Java基础语法 今日内容 数据类型 运算符 学习目标 了解进制 理解基本数据类型的自动类型转换 理解基本数据类型的强制类型转换 了解ASCII编码表和Unicode编码表 理解 ...

  6. JAVA基础语法——面向对象思想

    Java基础语法 前言 一.面向对象思想 1.面向对象(OOP)概述 2.面向对象三大特性五大原则 二.类和对象 1.对象和类的概念 2.对象的特征 3.构造方法 3.This关键字 4.static ...

  7. Java基础语法(数组)

    第4天 Java基础语法 今日内容介绍 u 流程控制语句(switch) u 数组 第1章 流程控制语句 1.1 选择结构switch switch 条件语句也是一种很常用的选择语句,它和if条件语句 ...

  8. Java基础语法(一)

    Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式 ...

  9. 【JAVA学习】1、零基础入门Java 基础语法:概念、规则、格式

    [JAVA学习]1.零基础入门Java 基础语法 前言 JAVA开发环境选择 Java 基础概念 Java 标识符 Java修饰符 基础代码模板框架 命名规则 基础规则 后端开发规则 代码格式 前言 ...

最新文章

  1. NuGet 无法连接到远程服务器-解决方法
  2. android地址格式转换,Android(安卓)时间戳和日期之间的转化
  3. Webservice开发之xsd中开发请求数据的响应接口
  4. 什么是RestTemplate
  5. python的rsa公钥解密方法
  6. Windows 7 :微软目前最好的操作系统
  7. java web的动静分离_如何做前后端动静分离
  8. linux5.5 里dns,linux red hat 5.5 dns 问题求解
  9. 计算机字处理软件word文档,2012计算机字处理软件 Word(answer)
  10. mysql数据库创建交叉表查询_sql – 我需要知道如何创建交叉表查询
  11. Asciidoctor Maven插件使用
  12. 8种常见的 代码 编译 软件 !!
  13. 通达信版弘历软件指标_弘历主图指标详解 通达信指标
  14. 听大神砍市场与软件开发的那些事儿
  15. 房产销售数据分析与可视化的设计与实现
  16. 关于语法节点Tree、类型Type和符号Symbol
  17. effect和watch 的区别详解
  18. 计算机网络安全的对策,计算机网络安全和对策.PDF
  19. 关于linux中DBG调试宏的使用总结,减少代码冗余
  20. java配置lib_javalib中文 java中的lib什么作用呢

热门文章

  1. html5 pjax,关于PJAX局部刷新
  2. highchart图表
  3. 中兴光纤猫 F420 破解
  4. 基于JAVA大学生心理咨询系统计算机毕业设计源码+系统+lw文档+部署
  5. Omni Recover for Mac(iPhone丢失数据恢复软件)
  6. 使用ps命令查看进程状态
  7. 保存文件_CAD文件如何进行实时保存确保过程文件不丢失
  8. java实现mysql数据库的一键备份,还原
  9. PyAutoGUI中文版文档
  10. 设置首页不出现页码的方法