MySql进阶

MySql进阶

存储引擎

MySql体系结构

image-20230422211947519

InnoDB是Mysql5.5以后默认的存储引擎

创建表的时候可以指定存储引擎

image-20230422212613696

查询当前数据库支持的引擎

show engines;

InnoDB存储引擎

简介

image-20230422213236299

逻辑结构

image-20230422213858445

MyISAM存储引擎

image-20230422214210823

Memory存储引擎

image-20230422214318474

存储引擎的特点

image-20230422214438313

image-20230422214701049

索引

索引概述

  • 介绍

    image-20230424163259008

  • 演示

    image-20230424163637942

  • 优缺点

    image-20230424163934965

索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包括一下几种:

image-20230424164325372

image-20230424164402235

  • 二叉树

    image-20230424164855812

  • B-Tree (多路平衡查找树)

    image-20230424165621719

    当存储的key等于阶数,此时会发生向上裂变

  • B+ Tree

    image-20230424170845206

b+树数据存储在叶子节点,并且叶子节点是链表

当存储的key等于阶数,此时会发生向上裂变,叶子节点但是向上裂变的同时还会存在于叶子节点,并且会生成一个单向链表

  • MySQL 对 B+ 树进行了优化

    image-20230424180828171

  • Hash索引

    image-20230424181346247

哈希索引特点

image-20230424181448593

当出现哈希冲突,就不是一次检索

存储引擎支持

image-20230424181547097

为什么采用B+树索引

image-20230424182031669

相对于hash索引,B+树支持范围匹配以及排序操作

索引分类

image-20230424182316227

在InnoDB 存储引擎中,根据索引的存储形式,可以分为以下两种

image-20230424182535674

聚集索引选取规则

image-20230424182649543

示例

image-20230424182920450

注:

聚集索引叶子节点下面挂载的是本行的数据,而二级索引叶子节点挂载的本行的id值

回表查询

​ 执行下面的sql语句,已知name字段建立了二级索引,此时条件为name等值查询,先走二级索引拿到id值,又因为查询的为所有字段,此时走聚集索引,根据id拿到本行的数据。

image-20230424183343891

索引操作语法

  • 创建索引

    image-20230424184617916

  • 查看索引

    image-20230424184730218

  • 删除索引

    image-20230424184744694

SQL性能分析

主要对查询语句进行优化

SQL执行频率

image-20230424190442889

1
show global status like 'Com_______';//7个下划线

image-20230424191251862

慢查询日志

查看慢查询日志是否开启

1
show  variables like 'slow_query_log';

image-20230424192030470

image-20230424191919635

image-20230424192055118

1
systemctl reastart mysqld; //重启mysql服务

profile详情

​ 数据库的 profiling 可以帮助我们分析数据库的性能瓶颈,了解每个 SQL 语句执行的消耗时间、I/O 操作、CPU 开销等细节。通过 profiling,可以发现程序设计和数据库调优中的问题,从而提升数据库的性能

可以查看sql语句耗时情况

1
show profiles;

image-20230424210104599

是否支持profiling

1
select @@have_profiling;

image-20230424212741795

是否开启profiling

1
2
3
select @@profiling;							//0是关闭,1是开启

set profiling = 1//开启profiling

image-20230424212606046

image-20230424213644300

explain执行计划

image-20230424214659353

image-20230424214838106

explain执行计划各字段含义

  • id

    image-20230424214949982

  • select_type

    image-20230424220906047

  • type(重要,越靠前性能越好)

    image-20230424220944594

  • possible_key(***)

    image-20230424221423449

  • key(***)

    image-20230424221534120

  • key_len(***)

    image-20230424221552133

  • rows(***)

    image-20230424221610128

  • filtered

    image-20230424221634697

  • Extra

    在前面的字段中没有显示的值会在这里显示

索引使用

验证索引效率

在未建立索引之前,执行sql语句,查看sql耗时

针对字段创建索引

1
create index 索引名称 on 表名(字段名);

注:在数据量较大时候,创建索引也比较耗时,创建索引成功之后,查询速度提升十分迅速

最左前缀法则

注意:只要存在创建索引时最左边的哪个索引就会走索引,与查询时索引所在的位置不同,否则就不会走

image-20230425104132248

​ profession,age 和 status建立了联合索引image-20230425104223116

注:最后两条sql跳过最左侧字段,导致索引失效,将不会走索引进行查询

  • 范围查询

    注意:这里右侧索引失效指的是创建索引时的右侧索引会失效,自己并不会失效

    image-20230425113228796

注:在业务允许的情况下,尽量使用 >= 可以解决范围查询索引失效问题

索引失效情况一

  • 不要在索引列上进行运算操作,该索引后面的索引将会失效

image-20230425113916890

  • 字符串不加单引号,索引将失效

    image-20230425114440545

  • 模糊匹配

    image-20230425190040439

总结

​ 范围不带等号,左边界模糊匹配,在索引字段上使用操作符,字符串不加引号会发生隐式转换,不遵守最左前缀树法则,在这几种情况下,索引会发生

索引失效情况二

  • or连接的条件

    用or分割的条件,只有两侧有索引的情况下,才会对索引进行触发

    image-20230425190955341

  • 数据分布影响

    image-20230425191347555

    数据分布占数据库表的大部分时,数据库会走全表扫描的情况

SQL提示

  • SQL提示,是数据库优化的一个重要手段,简单地说,就是在SQL语句中加入一些人为提示达到优化的目的

    image-20230425192314363

    use只是建议,MySQL不一定接受

覆盖索引(解决回表)

image-20230425192752115

image-20230425192815038

image-20230425193334062

前缀索引

解决大字段类型,在索引使用时浪费大量的磁盘io的问题

image-20230425195807590

语法

1
create index 索引名称 on 表名(column(n));           //n表示字符串前缀

前缀长度

image-20230425200050586

1
select count(distinct 字段)/count(*);                             //选择性,值越高,效率就越高

image-20230425204052589

单列索引和联合索引使用规则

联合索引能有效的规避回表查询,提高查询速度,对sql进行了优化

image-20230425204837084

image-20230425204852105

1
select id,name,phone from user where name='吕布' and phone='17799990000';

image-20230425205111627

上述sql语句执行时不需要回表查询,原因是该联合索引叶子节点挂载的是主键id,返回查询数据时,直接将索引和id一起返回,不需要回表

索引使用原则

image-20230425205748829

小结

image-20230425210513177

注:

在InnoDB存储引擎中必须有聚集索引,聚集索引一般为主键,没有主键,mysql会指派一个,聚集索引叶子节点挂载的是一行的数据

image-20230425211309852

SQL优化

插入优化

  • insert 优化

    批量插入(500-1000条比较合适),避免数据库网络连接浪费时间

    手动提交事务—避免事务的重复开启与关闭

    主键顺序插入

  • 大批量插入数据

    image-20230426200941186

    image-20230426201056354

1
2
3
4
5
mysql --local-infile -uroot -p   //参数--local-infile在登录数据库的时候加上

set global local_infile = 1; //设置全局参数local_infile为1,开启本地文件加载开关

load data local infile '/root/sqll.log' into table 'tb_user' fields terminated by ','lines terminated by '\n'; //执行load指令,将数据加载到表结构

主键优化

  • 数据的组织方式

    image-20230426202357725

    image-20230426202723182

  • 页分裂

    image-20230426203002248

    image-20230426205432266

  • 页合并

    image-20230426205611458

    image-20230426205813377

  • 主键设计原则

    • 满足业务需求的情况下,尽量降低主键的长度
    • 插入数据时,尽量选择顺序插入,选择AUTO_INCREMENT自增主键
    • 尽量不使用UUID做主键或者其他自然主键,如身份证号
    • 业务操作时,尽量避免对主键的修改

order by优化

image-20230426210235739

使用覆盖索引

image-20230426211350960

image-20230426211407328

image-20230426211718569

1
2
//大数据量排序时,可以适当增大缓冲区大小
show variables like 'sort_buffer_size';

group by优化

image-20230426211930550

当删除掉所有索引之后(使用临时表)

image-20230426212104098

创建索引之后(联合索引(age,profession)),只要符合最左前缀法则就会走索引

image-20230426212153475

分组条件只有age

image-20230426212348903

limit优化

limit分页,当数据量比较大时,数据量越大,性能会越来越低

例如

1
select * from emp limit 5000000000,10;

此条查询记录就是仅仅返回10条数据,其他数据丢失,查询条件巨大

优化思路,一般分页查询时,创建覆盖索引可以较好的提升性能,可以通过覆盖索引加上子查询方式进行优化

count优化

image-20230426214316194

优化思路:

自己计数

count用法

image-20230426214448733

image-20230426214904558

image-20230426214918944

image-20230426215020443

image-20230426215120963

update优化

image-20230426215804264

更新数据的时候尽量走索引,防止事务之间发生阻塞

总结

image-20230426220408410

视图,存储过程,触发器

视图

image-20230427092141355

  • 创建视图

    image-20230427092301334

  • 查询

    image-20230427092602346

  • 修改

    image-20230427093004350

  • 删除

    image-20230427093020780

视图检查选项

image-20230427094216994

cascaded :检查依赖视图条件

local:有酒检查,没有就不检查

存储过程

  • 介绍

    image-20230427113848748

  • 特点

    image-20230427114038568

  • 创建

    image-20230427114402534

    1
    2
    3
    4
    create procedure p1()
    begin
    select count(*) from sys_role_menu;
    end;
  • 调用

    image-20230427114411085

  • 查看存储过程

    1
    2
    //查看oa表中的存储过程
    select *from information_schema.ROUTINES where ROUTINE_SCHEMA='oa';

    image-20230428170856931

    1
    2
    //查看存储过程语句
    show create procedure p1;

    image-20230428171246222

    1
    2
    //删除存储过程p1
    drop procedure if exist p1;

变量

  • 系统变量

image-20230428172154624

  • 用户变量

    image-20230428173835377

  • 局部变量

    image-20230428180014373

    1
    2
    3
    4
    5
    6
    7
    create procedure p2()
    begin
    //声明局部变量
    declare stu_count int default 0;
    //为变量赋值
    select count(*) into stu_count from student;
    end;

    image-20230428180054536

if

image-20230428180652334

参数

image-20230428181406257

inout类型在输入之前先对变量进行赋值

case

  • 语法一

    image-20230428182649355

  • 语法二

    image-20230428182730334

    image-20230428193954097

    image-20230428194124035

while

image-20230428194056926

repeat

image-20230428195016494

loop

image-20230428195621601

image-20230428195701179

游标

image-20230428201736786

image-20230428201829471

条件处理程序

image-20230428205815303

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
create procedure p1(in uage int)
begin

declare uname varchar(100):
declare upro varchar(100);
//定义游标
declare u_cursor cursor for select name,profession from tb_user where age <= uage;

//退出条件是sql异常状态码
declare exit handler for SOLSTATE '02000' close u_cursor;

drop table if exists tb_user_pro;
create table if not exists tb_user_pro(
id int primary key auto increment.name varchar(100)
profession varchar(100)
);

open u_cursor
while true do
fetch u_cursor into uname ,upro;
insert into tb_user_pro values (null, uname, upro);
end while;
close u_cursor;
end;

存储函数

image-20230428214001269

触发器

  • 介绍

    image-20230429102801336

image-20230429103027127

  • 语法

    new.id是新数据的id new指代新数据

    old.id 是旧数据id old指代旧数据

    image-20230429103102120

小结

image-20230429120558634

  • 介绍

    image-20230429120831302

  • 分类

    image-20230429125535647

全局锁

image-20230429173419348

​ 未加锁,可读可写,数据不一致

image-20230429173906389

加上全局锁之后,只可读,不可写

image-20230429174114625

1
2
3
4
5
6
7
8
9
10
11
#加上全局锁
flush tables with read lock;

#直接在命令行窗口运行就行
#备份数据
mysqldump -u账号 -p密码 数据库名>[sql位置]:SQL名.sql;

#不加锁的一致性数据备份
mysqldump --single-transation -u账号 -p密码 数据库名>[sql位置]:SQL名.sql;
#释放锁
unlock tables;
  • 特点image-20230429175536304

表锁

​ 对于表级锁,主要分为三类

image-20230429175920460

  • 表锁

image-20230429175959137

1
2
3
4
5
#加锁
lock tables 表名 resd/write;

#释放锁
unlock tables/客户端断开连接

读锁不影响其他连接读,影响其他连接写,当前连接也不能写

image-20230429180223981

写锁,其他连接不能读也不能写

image-20230429180700730

image-20230429181005704

  • 元数据锁

    image-20230429181341615

  • 意向锁

    image-20230429182719662

    image-20230429182457637

image-20230429182838562

行锁

  • 介绍

    image-20230429184307248

image-20230429185008375

  • 行锁

    image-20230429185057737

image-20230429190732258

image-20230429185718048

  • 间隙锁(GAP)

    image-20230429190906369

小结

image-20230429194514218