mysql高级课程知识点

思维导图:
在这里插入图片描述
本篇文章主要是用来总结,java工程师对于mysql的性能优化,对于完美的mysql优化需要很深的工地,SQL语言入门很容易但是想要精通却很难,大公司一般都有专门的DBA用来完成该部分的工作.

在这里插入图片描述

索引(重点内容)

索引(Index):mysql官方给出的定义就是:索引是帮助mysql高效获取数据的数据结构,由此我们可以得到索引的本质其实是一种数据结构.可以简单的理解为是排好序的快速查找数据结构.(如果在面试的过程成被问到,千万不要直接说索引就像字典中的前面排好序的目录.)
在mysql中,数据库系统中还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据(也就是指针的意思),这样我们就可以在这些数据结构中实现高级查找算法,这种数据结构及时索引.下图就是一种可能的索引方式:
在这里插入图片描述
索引(官方给出的定义):

数据本身之外,数据库还维护着一个满足查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在数据结构的基础上实现高级查找算法,这种数据结构就是索引.

注意:我们在实际的开发环境中,和java程序员关系最好的一般都是DBA或者是运维工程师,关系最差的一般都是产品经理,其中DBA工作中很重要的一部分就是创建索引和索引的重建,java程序员在service层所写的delete方法,在最终很有可能不会执行SQL中的delete语句,极有可能执行的是update语句,(也有可能只是把该数据的标志位从激活状态修改为非激活状态),这样我们只是把该数据进行了逻辑删除,而不会进行真正的物理删除.这样做的好处,第一是可以保证我们数据的连续性,

为了数据分析,为了索引,我们一般都不会进行真正物理层面的数据删除.随着系统的运行,索引的指向可能会不准确,指向的不是我们想要的数据,当我们频繁的对数据进行修改,删除,新增,同一个可能索引指向的内存地址会频繁的改变,那么我们这个索引树(BTree)可能就会失效.修改数据不仅仅要改的是数据的本身,也要对相应的索引进行修改,这也是update语句效率下降的一个原因吧.

所以,需要频繁修改的数据时不太适合建立索引的,建立的索引是不完整的.

所以,DBA一般都会在晚上(java程序员下班后),锁表,然后对索引进行重建(为了保证索引的有效性,不会失效).

注意:索引本身也是很大的,它不可能全部存储到内存当中,因此索引往往是以索引文件的形式存储到磁盘上.

我们平常所说的索引,如果没有他别指明,说的都是BTree(多路搜索树,不一定是二叉树,)结构组织的索引,其中,聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+数索引,统称索引,当然了,除了B+树这种类型的索引之外,还有哈希索引(hashIndex)等

索引的优势和劣势

优势:

类似于大学图书馆建立书目索引,可以提高数据检索的效率,降低数据库的IO成本
通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗.

劣势:

实际上索引其实也是一张表,只不过该表时保留了主键和索引字段,并且指向实体表中的记录,所以索引咧也是要占空间的.
虽然索引大大提高了查询效率,但同时会大大降低了更新表的速度,例如对表进行,insert ,update和delete,因为在更新表时,mysql不仅要更新实体表中的数据,还要保存索引文件每次更新添加了索引列的字段.都会调整因为更新操作所引起的索引键值变化后的索引信息
索引只是提高效率的一个因素,如果你的mysql中含有大量数据的表,那么就需要花时间研究建立最优秀的索引,或者是优化查询语句.

mysql的索引分类:

单值索引:即一个索引只包含单个列,一个表中可以有多个单只索引.
唯一索引:索引列的值必须唯一,但是允许有空值.
复合索引:一个索引包含了多个列

总结:

对于一张表而言,大部分情况是建立复合索引优于单指索引.频繁使用的字段例如,银行系统中一般会按照两个字段进行单独查询,银行卡号,身份证号这种比较适合建立单值索引.
在中规中矩的情况下,一张表的索引数目不要超过5个.

基本语法:

创建索引:create [unique] index 索引名称 on 表名称(字段列表(length)) .
注意:如果索引列是 char ,varchar类型,length可以小于该字段的实际长度,如果是BLOB和Text类型,则必须制定长度.其中unique是唯一约束,是可以省略的.如果字段列表中只有一个字段,那么就是单值索引,多个字段就是复合索引.
创建索引:alter 表名称 add [unique] index [索引名称] on 字段列表(length)
删除索引:drop index [索引名称] on 表名称
查看索引:show index from 表名称.

使用alter创建索引的四种语法:

alter table 表名称 add primary key (column_list) :该语句添加一个主键,主键也是一种唯一索引,且不能为null.
alter table 表名称 add unique 索引名称 (column_list):该语句创建索引的值必须是唯一的(除了null值,因为null值可能会出现多次)
alter table 表名称 add index index_name (column_list):添加普通索引,索引值是可以重复的.
alter table 表名称 add full text index_name (column_list):该语句指定了索引为full text,用于全文索引.

mysql的索引结构:

BTree索引:
Hash索引:
full-text全文索引:
R-Tree索引:

注意:我们的索引树不是越高越好,同样的数据,索引树越低对数据库的IO访问次数越少,获取数据的效率就会越高.索引树尽量横向扩展,避免纵向扩展.

检索原理:
我们实际上对物理存储的划分,可以使用, 段,区 ,块三种来区分,
在这里插入图片描述
在这里插入图片描述

那些情况是需要建立索引的?
主键自动建立唯一索引
频繁作为查询条件的字段应当建立索引.
查询中雨其他表关联的字段,外键关系应当创建索引.
查询中排序的字段,如果你为Order by 中使用的字段建立了索引,那么查询该字段时将会通过索引访问将大大提高排序速度.
查询中需要统计或者是分组的字段,(分组的前提就是排序,group  by也和索引嘻嘻相关)
那些情况是不适合建立索引的?
频繁更新的字段是适合建立索引的,因为,每次的更新不单单会更新数据,还会造成索引树的更新,增加了IO负担.
where筛选条件中用不到的索引是不用创建索引的.
在单值(单键)和符合(组合)索引中,我们更加倾向于复合索引,尤其是在高并发的环境下.
表中的记录太少(mysql的性能还是很强悍的,官方给出的是数据在 5~800 万之间都是可以的,但是一般在300万数据的时候性能都会有明显的下降,我们就需要进行调优了)
数据重复,且分布比较的平均的字段不用建立索引.因此我们需要为最经常查询,最经常排序的字段建立索引,
如果一个字段的内容中,包含了很多的重复的值,那么我们没必要建立索引.

公式:(该公式可以计算出一个列建立索引的可选性)
在这里插入图片描述
总结: S = 索引列中不相同的值的总个数 / 表中的总记录数 ,如果S的值越接近1,就说明该字段就越适合建立索引,效率也就越高.

mysql中常用的性能分析

(1) Mysql Query Optimizer
(mysql 查询优化器,位于mysql的逻辑架构中的第二层,服务层,一般我们都是使用mysql默认的,技术大牛可以自己写查询优化器)

1.mysql中有专门负责优化的select查询语句的优化器模块,主要功能就是,通过计算分析系统同收集到的统计信息,位客户端请求的Query提供它(Mysql)认为的最优的执行计划(它认为是最	优的数据检索方式,但是不见得是DBA认为的最优的,这部分最消耗时间)
2.当客户端向mysql请求一条Query,命令解析器模块会完成对请求的分类,区别出是select并转发给 Mysql Query optimizer,mysql query  optimizer首先会对整条query进行优化,处理掉一些常量表达式的预算,直接换算成常量值,并且对query中的查询条件进行简化和转换,比如去掉一些无用或显而易见的条件,结构调整等.然后分析Query中的Hint信息,(如果有的话),看显示Hint信息是否可以完全确定该Query的执行计划.如果没有Hint或者是Hint不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query进行写相应的计算分析,然后在得出最后的执行计划.

(2) Mysql常见瓶颈

CPU:CPU在饱和一般发生在数据装入内存或者是从磁盘上读取数据的时候.
IO:磁盘I/O瓶颈发生在频繁装入数据远大于内存容量的时候.
服务器硬件的性能瓶颈:该部分可以细分为两个部分,第一就是,物理设备硬件的不足,这个只能购买性能更好的机器.第二 ,就是我们自己的配置的问题,比如 sortbuffer配置太小等,这种情况我们可以通过top ,free ,iostat和vmstat等命令,来查看我们当前系统的性能状态.

(3) Explain
如果 mysql query optimizer 我们没有任何的修改,mysql常见瓶颈也都没有出现,那么我们就需要调出分析报告来查看到底是mysql中的那部所导致的的.

Explain是什么

Explain关键字主要是用来查看执行计划的,使用Explain关键字可以模拟优化器执行SQL查询语句,从而知道mysql是如何处理你的SQL语句的,分析你的查询语句或是表结构的性能瓶颈

Explain能干吗:

表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被实际使用
表之间的引用
每张表有多少航被优化器查询

Explain怎么玩:****(重点,难点,也是和HR侃的资本)

explain + 你要执行的SQL语句

执行计划包含的信息:
在这里插入图片描述
图片上各个字段的解释如下:

explain的id字段

id:它的值表示的是select语句的序列号,包含一组数字,表示的是查询中执行select字句或者是操作表的顺序.它的取值有三种情况:

id相同:

	它表示的是mysql内部的查询优化器,执行主人命令或者说成是加载表的顺序是顺序的,是由上带下的进行执行的.

在这里插入图片描述

id不同:

id不同,如果是子查询,id的值序号会递增,id的值越呆,表示的是当且表的优先级就会越高,越先被执行.

在这里插入图片描述

id相同和不相同 ,同时存在:

id如果是相同的,那么可以认为是一组,从上往下顺序执行.
在所有的组中,id的值越大,优先级就越高,就越容易被先执行

在这里插入图片描述

explain的select_type字段

select_type的主要作用就是用于区别出普通查询,联合查询,子查询等的复杂查询select_type 的取值:

simple:简单的select查询,查询中不包含子查询或者是union
primary:主查询,查询中如果包含子查询,最外层的查询则称为主查询
subquery:子查询 ,在select或者是where列表中包含的子查询
derived:衍生表,在from列表中包含的子查询称为是衍生表,mysql会递归执行这些子查询,把结果集放到临时表中.(临时表有时候会增加协同负担,但是又不得不使用)
union:如果select车现在union之后,那么就会被标记为union,如果union包含在from列表中的子查询之中,那么外层的select则会被标记为derived.
union result:从union表中获取结果的select,其实就是union前后语句执行结果的合并.

explain的type字段.

type字段的值可以反映出我们的SQL是否进行过优化.常用取值有如下图片所示:
在这里插入图片描述
所有取值由最好到最差的排列如下:
system -->const --> eq_ref --> ref --> range --> index --> all
type表示的访问类型,all表示的是全表扫描,是没有进行过SQL优化的,一般来说,查询至少要优化到range级别,做好能够达到ref级别.

system:代表的是表只有一行记录(相当于是系统表).这个是const类型的特例,平时不会出现.
const:常量,表示通过索引一次就找到了,const主要是用来比较primary key或者unique索引.因为只匹配一行数据,所以会很快.如果将主键放置在where列表中,mysql就能将该查询转变为一个常量.
eql_ref:唯一性索引扫描,对于每个索引建,表中只有一条记录与之匹配,常见于主键或者是唯一索引扫描
ref:非唯一性索引扫描,返回匹配某个单独值的所有行,它的本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而他可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体.
range:范围,只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出现了 between >  <  in 等的查询,这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点.不用全部扫描索引.
index:fullindex scan,index和all的区别就在于,index类型是只遍历索引树,这通常比all要快,因为索引文件通常比数据文件要小,(也就是说,虽然index和all都是读取全表,但是index是从索引中读取的,而all是从硬盘上读取的.)
all: full table scanner :全表扫描.

explain的possible_keys,key和Key_len字段

possible_keys和Key这两个值只要是用来判断你的SQL语句中是否使用到了索引,以及索引是否失效还有就是在多个索引竞争的情况下,你的mysql到底使用到 了哪一个索引

possible_key:显示的值是可能应用在这张表上的索引.可能有一个也可能有多个.如果查询语句中的字段上存在索引,那个该索引将被列出,但是不一定被查询实际使用.
key:就是指在查询中真正使用的索引,如果为null那么要么就是没有建索引,要么就是建索引了但是没有使用.如果查询中出现了覆盖索引,那么该索引只出现在key列表中.
覆盖索引:简单来说,就是我们要查询的字段和建立复合索引的字段的个数和顺序一一对应,例如,我们在colm1和colm2连个字段上建立一个复合索引,而我们查询语句中写的不是select * ,而是select colm1,colm2 from xxx.要查的字段刚好和建立索引的字段匹配,并且顺序是一致的.这样的索引就覆盖索引.

在这里插入图片描述

key-len:它表示的是索引中使用的字节数,我们可以通过该列来计算出查询中使用的索引的长度,在不损失精度的情况下,长度是越短越好.
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len使根据表定义计算而得,并不是通过表内检索得出的.

explain的ref字段

刚才提到的ref其实是type的一个值,这个ref是和type是一个级别的,要把二者却别开.

ref:显示出索引的哪一列被使用了,如果可能的话,是一个常数,它会显示出哪些列或者常量被用于查找索引列上的值

在这里插入图片描述

explain的rows字段

rows:它的作用就是根据表统计信息,以及索引的选用情况,大致估算出找到所需记录所需要读取的行数.它的值的可以表示每张每张表有多杀行被查询优化器查询.它的值越小越好.

explain的extra字段

由于要显示的信息太多,一行结果展示有限,mysql就把很多不适合在其他列中显示但却是十分重要的信息放在这里面,它可以有多个值.字面翻译就是额外的.
(普通的 explain SQL 执行完成之后都是以横版显示的, explain SQL\G会把键值对以竖版的形式显示)
取值和解释如下

(1) Using fire sort

它被称为是文件内排序,说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取.mysql中无法利用索引完成的排序称为是文件内排序.(如果出现了这种情况,比较危险,几乎是九死一生了)

在这里插入图片描述

(2) Using Temporary
它使用了表示mysql在执行SQL过程中使用了临时表用来保存中间结果,mysql在对查询结果进行排序时会使用临时表,常见于分组 order by和分组查询group by.它的出现几乎是 "必死无疑 ",到后期的case中,我们表的数据都是千万级别的数据量,临时表的创建其实是很伤系统性能的,它要进行数据从磁盘到临时表的复制,SQL执行完成之后,再把临时表进行回收.这些操作都是在mysql的内部完成,由于数据量较大,会给mysql带来很大的负担.
在这里插入图片描述

(3) Using Index
出现这种情况其实是好事,不想之前那两种那么可怕,他表示的就是相应的select操作中使用到了覆盖索引(Covering Index),避免访问了表的数据行,效率不错,(注意,覆盖索引只出现在Key列中.)
在这里插入图片描述
注意:如果要使用覆盖索引,一定要注意select 列表中只写需要的列,不能写select *

如果同时出现了Using where,表示索引被用来执行索引键值的查找.
如果没有同时出现Using where ,表示索引用来读取数据而非查找操作.

(4) Using where
表示使用了where过滤

(5) Using join buffer
使用了连接缓存,如果我们的SQL中join过多,就会出现join buffer ,我们可以修改配置文件中的join buffer 的参数,设置大一点.

(6) Impossible where
表示的是where子句的值总是false,不能用来获取元组.
在这里插入图片描述
Explain热身case:
join语句优化的结论:

尽可能的减少join语句中的NestedLoop的循环总次数,"永远用小表来驱动大表",如果翻过来用大表驱动,会有比较频繁的IO
优先优化NestedLoop(嵌套循环)的内层循环(因为只有内层循环执行的效率快,才能尽快的执行外层)
保证join语句中被驱动表(大表)的join条件的字段已经被索引
当无法保证join条件中被驱动表(大表)的join条件的字段被索引,并且内存资源充足的情况下,不要太吝啬joinbuffer的设置,要把数值设置大一点.

索引的优化以及如何避免索引的失效(重点)
java开发过程中常见的索引失效的各种原因:
在这里插入图片描述
1.全值匹配我最爱
指的是,我们的SQL语句正好能够按照我们的索引字段的顺序使用,并且是一一对应的.

如果我们的索引是复合索引,那么我们索引的最左侧的字段,可以称为是带头大哥,

2.最佳左前缀法则
它是指,如果索引了多列,我们要遵守最佳左前缀法则,指的是查询从索引的最左前列开始,并且不跳过索引中的列.

带头大哥不能死
中间兄弟不能断(永远要复合最佳左前缀原则)
索引列上无计算(包括,计算,函数,手动,自动的隐式或者显式的类型转换)
like%加右边
范围之后全失效
字符引号不能少

3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
在这里插入图片描述
4.存储引擎不能使用索引中范围条件右边的列
在这里插入图片描述
5.尽量使用覆盖索引(只访问索引的查询(查询列和索引列保持一致,就算不一致,最好也要在索引列的范围内波动)),减少select * 的使用

我们在查询的时候,还是按需检索数据,需要多少取多少,尽量减少select * 的使用.

在这里插入图片描述
6.mysql中使用不等于号 != (或者是 <>)无法使用索引,会导致全盘扫描
在这里插入图片描述
7.is null 和 is not null也是无法使用索引的
在这里插入图片描述

is null和is not null还是有点不同的,is null的type的值是null 是一种极端情况,而is not null 的type取值是 all表示的是全表扫描.

8.(重点) like以通配符开头(例如:%abc%),会导致mysql的索引失效,而变成全表扫描
在这里插入图片描述

注意:面试题:解决SQL中 like%字符串% 索引失效的方法 ? ? ?

我们都知道,如果使用了通配符like,只有%加载like的右侧,索引才不会失效,但是在实际生产环境中,我们可能不得不写 like%str% 这样字符串两侧都有%的SQL,少写了一个%可能查出来的就不是我们想要的结果,
使用覆盖索引可以有效的解决这个问题,我们皆可以写两个% ,也可以避免索引失效.再次强调覆盖索引,如果我们索引了多列,并且我们的查询列表和索引字段的个数和顺序是一一对应的,那么我们就是使用了覆盖索引.
注意:如果我们在实际情况中,查询列表并没有和覆盖索引字段完全吻合,但是在覆盖索引字段的范围内波动,索引也是可以使用的,不会失效.但是如果 我们的查询列表的范围,超过了索引字段,例如,select *和select 全部字段,就会导索引失效.

9.(重点) 字符串不加单引号所导致索引失效
注意:在开发环境中,如果你的varchar类型的字段在SQL中忘了添加单引号,那么一很有可能会被项目经理骂死.varchar类型的字段绝对不能失去单引号.
在这里插入图片描述
10.少用or,因为用它连接时会导致索引失效
注意:少用并不是不用的意思.
在这里插入图片描述
小总结:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第三章 查询截取分析

本章内容包含以下
在这里插入图片描述
在面试中,如果被问到,你对SQL优化有什么认识?
explain(使用explain进行sql分析)

观察,至少跑一天,看看生产的慢SQL的情况
开启慢查询日志,设置阙值,比如超过5秒的就是慢SQL.并将它抓取出来.
explain+慢SQL分析(当我们执行到这一步的时候,差不多会有8成的SQL可以得到优化)
show profile 再次对SQL进行分析,它的颗粒度比explain还要细(这一步差不多可以99%)
运维经理或者是DBA进行SQL数据库服务器的参数的调优(这一步不需要java工程师)

SQL优化总结如下:
1.慢查询的的开启和捕获
2,explain + 慢SQL分析
3,show profile 查询SQL在mysql服务器内部的执行细节和生命周期情况
4,SQL数据库服务器的参数的调优

查询优化
1.永远要小表驱动大表
在这里插入图片描述
谈谈 in 和 exits 关键字的理解:
在这里插入图片描述
在这里插入图片描述
2.orde by 关键字优化
对于order by 排序,我们只关心一个问题, 会不会产生 filesort排序.
order by 默认是按照升序进行排列的.

在这里插入图片描述
在这里插入图片描述

order by 字句尽量使用 Using index 排序,避免使用 Using Filesort排序
尽可能在索引列上完成排序,遵照索引建的最佳左前缀法则(因为我们在建立索引的时候已尽给排序了,如果我们按照索引字段进行排序,便可以减少一次排序.)
如果不在索引列上完成排序,filesort会有两种排序算法:mysql就会启动双路排序和单路排序

mysql支持两种方式的排序,filesort 和 Index 其中Index的效率是比较高的,它是指mysql能够通过索引本身完成排序,而filesort方式的效率较低.也就是说,使用Using Index 是优于Using filesort.

order by满足两种情况会使用Index排序:

order by语句使用索引最左前列(最佳左前缀法则依旧适用)
where子句和order by子句组合在一起满足索引最左前列(还是符合最左前缀法则)

双路排序,单路排序,结论和引申出的问题

双路排序:

mysql4.1之前使用的都是双路排序(现在的公司一般用的都是5.0之后的版本),字面意思就是,**两次扫描磁盘**,最终得到数据.读取行指针和order by 的列,对他们进行排序,然后扫描已经排好序的列表,按照列表中的值重新从列表中读取对应的数据输出.
从磁盘中取排序字段,早sortbuffer中进行排序,在从磁盘中取其他字段

双路索引,取一次数据,要对磁盘进行两次扫描,众所周知, I/O是很耗时的,所以在mysql4.1之后,出现了第二种改进的算法,就是单路排序.

单路排序

从磁盘中读取查询需要的所有列,按照order by列在sortbuffer中对他们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据,并且把随机IO变成了顺序IO,但是他会使用更多的空间,因为它把每一行都保存在了内存中.

引申出的问题
对于双路排序而言,无论是磁盘有多少数据,总是可以能通过两次扫描磁盘拿到所有数据,虽然效率有点低,但是对于单路算排序而言,如果数据量在一定的范围内(即,一次排序可以取出所有的数据),那么它的效率是比双路排序高的,但是如果数据量过大,由于内存大小有限,一次取出的数据时有限的,它也需要进行多次的磁盘扫描.这时它的效率就不如双路排序了.简单而言,就是"一次抓完是单路,抓不完就比较坑爹了"
在这里插入图片描述
针对上述问题的优化策略
这两种优化策略都属于是mysql服务器参数的调优

增大sort_buffer_size参数的设置
增大max_length_for_sort_data参数的设置
不要使用 select * ,只写需要的字段.

在这里插入图片描述
为排序使用索引的总结
总结就是,我们为查询索引所使用的法则完全适用于排序索引.如果我们的索引既能够比查询使用,也能够被排序使用,那是再好不过的了啊
在这里插入图片描述

3.group by 关键字优化

group by实质上时先进行排序,再进行分组.它也是遵照索引的最佳左前缀法则
当无法使用索引时,要增大sort_buffer_size和max_length_for_data参数的设置
where高于having,能卸载where的限定条件,就不要卸载having之后了

慢查询日志
(1)是什么,怎么玩
在这里插入图片描述
注意:

默认情况下,mysql是没有开启慢查询日志的,需要我们手动设置这个参数
当然,如果不是调优的情况下,一般是不建议启动改参数的,因为开启慢查询日志,或多或少会带来一定的性能影响,慢查询日志支持将日志日志记录写入文件

show variables like “%slow_query_log%”:查看是否开启慢查询日志
set global slow_query_log = 1 :开启慢查询日志.
在这里插入图片描述

注意:

使用set global slow_query_log = 1 这个命令,开启慢查询日志,只是针对当前的数据库是有效的,如果mysql重启就会失效.
如果想要永久生效,就必须修改配置文件 ,my.cnf(其他的系统变量也是如此),在[mysqld]下,增加或者修改参数,slow_query_log = 1 和 slow_query_log_file= /var/lib/mysql/Hadoop-slow.log然后重启服务器即可
关于slow_query_log_file这个参数,他指定的是慢查询日志文件的存放路径,如果我们没有给它指定文件名称的话,默认会给一个缺省文件的名,即,当前登录的用户所在的home路径-slow.log

如何定义一个SQL到底慢不慢呢?哪些SQL会被记录到慢查询日志中呢?

这个是由参数long_query_time的值决定的.默认情况下,long_query_time的值是10秒,但是在实际的生产环境中,10秒的SQL根本就不太现实,所以,我们可以使用命令进行修改,也可以修改配置文件my.cnf.如果sql的执行时间正好和query_long_time的值相等的话,该sql是不会被记录的,所以,query_long-time 只记录比阙值大的SQL.

在这里插入图片描述
set global long_query_time = 3 :设置阙值 .设置之后我们再次查看阙值还是之前的值,?? 不是我们的命令无效,其实已经做出了修改,但是我们需要重新连接或者打开一个会话才能看到修改过后的值.

通过配置文件进行修改阙值和慢查询SQL的文件位置:
在这里插入图片描述

记录慢SQL并且分析
在这里插入图片描述
在这里插入图片描述

我们可以再打开slow-query_log_file,然后把那些执行时间超过阙值的SQL抓取出来,进行分析和优化.

show global status like “%slow_queries%”:查询系统中总共有多少条慢SQL.该语句可以作为我们当前系统的健康检查,如果查出来有大量的SQL超过了阙值,那么系统的性能就需要调优了.
在这里插入图片描述
(2)日志分析工具 mysqldumpslow
在生产环境中,如果要手动的分析日志,查找,分析SQL,显然是个体力活,mysql为我们提供了日志分析工具,mysqldumpslow.

mysqldumpslow --help :他可以帮助我们获取到mysqldumpslow的帮助信息.如果你的执行结果是,bash: mysqldumpslow: command not found,的错误,没关系,请执行 ln -s /usr/local/mysql/bin/mysqldumpslow /usr/bin;创建一个软链接即可.
在这里插入图片描述
针对各个参数的解读如下:
在这里插入图片描述
工作过程中常用的参考:
在这里插入图片描述
批量数据脚本
复习一下:函数和存储过程.
二者都是完成批量操作的,但是存储过程是没有返回值的.如果我们需要往数据库中插入1000万条记录,不提倡一次性插入,可以分批次执行,例如每次插入50万,执行20次.可以减轻数据库服务器的压力.
但是函数是有返回值的,人存储过程句没有.
show profile
它是一个比explain的粒度还要细的一个排查手段,一般到了这个地步,SQL的优化大部分都能够实现,但是如果还不能很好的优化SQL,那我们就需要配合着DBA去修改my.cnf文件写进行各种节点和性能参数的调优.

它是mysql提供用来分析当前会话中语句执行的资源消耗情况,可用于SQL的调优的测量.在默认的情况下,它的参数是处于关闭的状态,并且保存最近15次的运行结果.

步骤入戏

1 是否支持,查看当前的的mysql版本是否支持

show variables like ‘profiling’
在这里插入图片描述
或者使用,show variables like ‘profiling%’

2 开启功能,默认是关闭的,使用前需要开启.

set profiling = on; 开启此功能.
在这里插入图片描述

只要开启了show profile,它就会在后台偷偷的记录着我们执行的SQL
3 运行SQL
4 查看结果.

在这里插入图片描述

5 诊断SQL show profile cpu,block io for query 具体sql的id值

当然了,我们只是列举了其中的两项参数,具体的参数如下图:
在这里插入图片描述

6 日常开发需要注意的结论

出现了下面4条中的一条,我们就需要对SQL进行优化了,他们都是耗内存的.

Coverting HELP to  MyISAM 查询结果太大,内存都不够用了,往磁盘上搬了
Creating tem table 创建临时表 (它会拷贝数据到临时表,当把数据展示给用户之后再删除临时表)
Coming to tmp table on disk 把内存中的临时表复制到磁盘 危险 !!!!!!!!
locked 

在这里插入图片描述
全局查询日志
曲剧查询日志,在某些条件下也可以帮助我们进行SQL的性能优化,但是有的一点要注意,就是,一定要在测试环境下使用,永远不要在真正的生产环境下开启这个功能.

启动方式分为两种:
第一种:(配置启用)

在mysql的my.cnf中,设置如下:(1) 开启,general_log = 1
(2)记录日志文件的路径  general_log_file = /path/logfile
(3)输出格式  log_output = FILE

第二种:(编码启用)

set global general_log = 1
set global log_output= 'table'

启动之后,我们编写的所有的SQL语句都会被记录在mysql的general_log表中,我们可以通过,**select * from mysql.general_log;**进行查看.

在这里插入图片描述
show profile和全局查询日志我们都可以用来查询出SQL的执行星狂,但是推荐使用show profile.因为它能体现出一个SQL在生命周期的每一步中的耗时和内存等占用.

四 ,mysql的锁机制
锁的概述

	锁,是计算机协调多个进程或线程并发访问某一资源的机制.
	在数据库中,除了传统的计算资源(例如,CPU,RAM,I/O等)的争用外,数据也是一种共许多用户共享的资源,如何保证数据并发访问的一致性,有效性,是所有数据库都必须解决的问题,锁冲突也是影响数据库并发发访问性能的一个重要因素,从这角度来说,锁对数据库就显得尤为重要,也更加复杂.

在这里插入图片描述
锁的分类
按照对数据操作的类型分:

读锁(共享锁):针对同一份数据,多个读操作可以同时进行并且不会相互影响.
写锁(排它锁):当前操作没有完成前,它会阻断其他读锁和写锁.

按照对数据操作的粒度分:

行锁(偏写)
表锁(偏读)

对于锁,我们应该是下图中的态度,不能一概而论说哪一种锁最好.
在这里插入图片描述
表锁,行锁,页锁 的特点

表锁:偏向于MyISAM引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
案例结论:
在这里插入图片描述

MyISAM引擎在执行查询语句(select)之前,会自动给涉及到的所有表加读锁,在执行增删改操作之前,会自动给涉及到的表加写锁.
结论:(对MyISAM进行操作,会有以下情况)
	1.对MyISAM的读操作(加读锁),不会阻塞其他进程对同一张表的读请求,但是会阻塞对同一张表的写请求,只有读锁释放后,才会执行其他进程的写操作.
	2.对MyISAM的写操作(加写锁),会阻塞其他进程对同一张表的读写操作,只有当写锁释放之后,才会执行其他进程的读写操作

总结出来就是一句话:(也可以说成是mysql的读锁和写锁的区别,可以直接写在面试题上)

读锁会堵塞写操作,但是不会堵塞读,而写锁会堵塞读和写操作

show open tables :查看那些表被加锁了(值是1的表属于加锁了,为0的表示是没加的)
show status like ‘table%’:
在这里插入图片描述
MyISAM不适合做以写操作为主表的原因:
在这里插入图片描述
在这里插入图片描述
行锁
特点如下:

偏向于InnoDB存储引擎, 开销大,加锁慢,会出现死锁,锁粒度最小,发生锁冲突的概率最低,并发度最高

InnoDB和MyISAM的最大不同点在于:

InnoDB是支持事务的(TRANSACTION),然后是InnoDB是支持行锁的.

由于行锁是支持事务的,所以我们要复习一下:(面试题中经常考)

1.事务(Transaction)及其ACID属性

事务,它是由一组SQL组成的逻辑处理单元,事务具有以下4个属性,通常简称为ACID属性.

在这里插入图片描述

2.并发事务处理带来的问题

更新丢失(Lost update):
脏读(Dirty Reads):
不可重复读(Non-Repeatable Reads):
幻读(Phantom Reads):

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.事务的隔离级别

读未提交(Read uncommitted)
读已提交(Read committed)
可重复读(Repeatable Read):mysql的默认的事务的隔离级别.
序列化(Serializable)

在这里插入图片描述
show variables like ‘tx_isolation’:查看当前数据库的事务隔离级别.
在这里插入图片描述

mysql 默认的事务隔离级别是 Repeatable Read,可重复读,一般而言是可以避免 脏读和不可重复读的.但是有可能会出现幻读.

在这里插入图片描述
==史诗级灾难片之 无索引 行锁升级成表锁 ==
建立索引但是使用不当会导致行锁升级成表锁,varchar类型一定要放在单引号中,不然是重罪
在这里插入图片描述
下图中 索引失效导致行锁升级成表锁,造成阻塞:
在这里插入图片描述
史诗级灾难片之 间隙锁危害

在一些公司中,系统的数据很珍贵,业务逻辑层中写的delete方法其实在执行到mapper时,底层调用的是update方法,并不是真正的delete方法.只是逻辑上的删除,并不是真正物理意义上的删除.

在这里插入图片描述
在这里插入图片描述
上图就是发生了间隙锁,
在这里插入图片描述

间隙锁其实通俗的来说属于是,宁可错杀,绝不放过类型的,只要是你的索引键值在它的范围之内,它就会对该范围进行加锁,不管你的键有没有值存在,加锁期间,其他会话不能对该范围执行插入操作,这会对性能造成很大的危害.

面试题:常考如何锁定某一行
在这里插入图片描述
在这里插入图片描述
show status like ‘%innodb_row_lock’:可以用来分析系统上行锁的争抢情况
在这里插入图片描述
在这里插入图片描述

行锁的总结:

尽可能让所有的数据检索都通过索引来完成,避免无索引导致行锁升级成表锁
合理设计缩进,尽量缩小锁的范围
尽可能减少索引条件,避免间隙锁
尽量控制事务的大小,较少锁定的资源量和锁定时长
尽可能低级别事务隔离

猜你喜欢

转载自blog.csdn.net/dawiebazhanlang/article/details/88140787
今日推荐