带你走进Mysql的底层优化

Mysql的分层
在这里插入图片描述
InnoDB和MyISAM区别?

InnoDB(默认):事务优先(适合高并发)行锁
MYyISAM:性能优先,表锁
引擎原理
show ingines;查看数据库引擎
指定数据库表的引擎:
create table tb(
id int(4) auto_increment,
name varchar(5),
dept varchar(5),
primary key(id)
)engine=MyISAM auto_increment=1
default charset=utf-8;

SQL优化
原因:性能低,执行时间长,等待时间长,sql语句写的不好。索引失效,服务器参数不合理。
sql编写:select …from …join …on …where … group by … having … order by … limit …
sql编译:from … on …join … where … group by … having … select …order by …limit.
详解:https://www.cnblogs.com/annsshadow/p/5037667.html

sql优化主要优化索引。
索引:相当于书的目录
索引:是帮助Mysql高效查询的数据结构,一般是B+树
索引弊端:
1.索引本身很大
2.索引不是所有情况都适用a少量数据b不经常修改的数据
3索引会降低增删改
索引优势:
1.提高查询效率(降低IO使用率)
2.降低CPU使用率,B树已经排好序了
在这里插入图片描述
3层B-tree能存放上百万数据。
B+树,真是数据都是存放在叶子节点上,非叶子节点上都是冗余的。加快查询速度。
不管查询哪个数据都需要n次。
索引的分类
单值索引:单列,age,一个表最多16个索引,可以多个索引
主键索引:不能重复,一般为id
复合索引:多个列共同索引(name,age)
创建索引

方式一:
create 索引类型 索引名 on 表(字段)
单值:create index dept_index on tb(dept);
唯一:
create unique index name_index on tb(name);
符合索引:
create index dept_name_index on tb(dept,name);
方式二:
单值:
alter table tb add index dept_index(dept);
唯一:
alter table tb add unique index name_index(name);
复合索引:
alter table tb add index dept_name_index(dept,name);
DDL语句不用提交。
如果一个字段是promary key 该字段默认是主键索引。
主键索引和唯一索引的区别就是主键索引不能为null。
删除索引:
drop index 索引名 on 表名;
drop index name_index on tb;
查询索引:
show index from tb;
SQL性能问题
a分析SQL的执行计划:explain 可以模拟sql优化器执行sql语句
bMySQL查询优化会干扰我们的优化
在这里插入图片描述
在这里插入图片描述
select t.* from teacher t,course c,teacherCard tc where t.tid=c.tid and t.tcId=tc.tcid and (c.cid=2 or tc.tcid=3);
在这里插入图片描述
id值都为1,从上往下顺序执行。t 3,tc3,c4
tc3 c4 t5
表的执行顺序根据数据条数越多越后面执行。
原因:笛卡尔积。345=12*5 数据量小优先执行
id值不同时,id值越大越优先执行。
查询教授sql课程的老师的描述语句。
select tc.tcdesc from teacherCard tc ,course c,teacher t where tc.tcid=t.tcId and t.tid=c.tid and c.cname=‘sql’;
将多表操作变成子查询。
explain select tc.tcdesc from teacherCard tc where tc.tcid=(
select t.tcId from teacher t where t.tid=(
select tid from course c where c.cname=‘sql’
)
)
在这里插入图片描述
id值不同,id越大越优先执行,先查内层在查外层。
id值有相同有不同,先查id值大的,id相同的从上往下顺序执行。
select_type:
PRIMARY:包含子查询SQL中的主查询(最外层)
SUBQUERY:包含子查询SQL中的 子查询(非最外层)
simple:简单查询
derived:衍生查询(使用临时表)
a.from的子查询中只有一张表
b.在from子查询中,如果table1 union table2 则table1就是derived
在这里插入图片描述
type:索引类型
system>const>eq_ref>ref>range>index>all
越往左效率越高,其中system,const只是理想情况,实际能达到的在ref>range
要对type优化的前提是有索引。
system:只有一条数据的系统表
const:仅仅能查到一条数据的sql,用于主键或者唯一键
eq_ref:唯一性索引,对于每个索引键的查询,返回匹配唯一行数据(索引的值唯一的);常见于唯一索引和主键索引。teacher表的数据个数和连接查询的数据个数一致(都是3条数据),有可能满足。
ref:非唯一性索引,对于每个索引建,返回匹配多个行。
range:范围查询,按照索引列差一个范围。between and < > in or
index:查询全部索引中的数据
all:查询所有表中数据 。

key_len :索引长度
ref:作用:指明当前表所参照的字段。const是常量,where后用的字段
rows:被优化后的数据个数。实际通过索引插叙到的数据个数。
Extra:usingfilesort 性能消耗大,需要额外一次的查询或排序,排序和查找是同一个字段不会出现。
复合索引:不能跨列(最佳左前缀)–usingfilesort
using temporary:性能损失大,会多创建临时表,常见于group by中。需要额外多使用一张表。
using index:性能提升,索引覆盖。说明不读取源文件了,从索引查询。

SQL优化:
建议索引的使用顺序跟索引创建顺序一致。,虽然编写的顺序与执行顺序不一致,sql优化器会帮助优化。
where和order by 不能跨列使用。
复合索引最左原则:a1a2a3a4 用的时候a1,a4,a2,a3此时a4会失效。部分一致,使用部分索引。使用顺序和创建顺序一直都使用。
单表优化:
1.根据实际解析sql语句的顺序加索引顺序。
2.索引不能跨列使用(最佳左前缀)
3.索引需要逐步优化
4.in的范围查询放在最后,防止失效。
多表优化:
小表驱动大表,小表放左边,大表放右边,外层越小执行越快。
索引建立在经常使用的字段上。左外连接给左表加索引,右外连接给右表加索引。

避免索引失效的原则
a复合索引不要跨列或者无序使用
b尽量使用全索引匹配。
c不要再索引上进行任何操作(计算,函数,类型转换)
d对于复合索引,左边索引失效,右边全部失效,最左原则
e复合索引不能使用!= 或者<>或者is not null否则自身及右边索引全部失效(概率情况,因为Mysql底层有sql优化器)
f。 like尽量以常量开头,不要以%开头,否则索引失效。
g 不要使用类型转换,会使索引失效,数字转字符串。
h 不要使用or,否则索引失效。

学习索引优化,是一个大部分情况适用的结论,但由于sql优化器等原因,该结论不是100%正确。

其他优化方法:
1如果著查询的数据集大,则使用in,如果子查询的数据集大则使用exisit
2.order by优化 单路排序,双路排序,可以调整buffer容量大小,避免select * ,复合索引不要跨列使用,保证排序的一致性(都是升序或者降序)
慢查询日志,用于记录响应时间超过阈值的sql语句。默认10s,默认关闭满查询日志。show variables like ‘%slow_query_log%’;
临时开启:set global show_query_log=1 —再内存中开启,服务重启关闭。
永久开启:my.cnf 追加slow_query_log=1 slow_query_log_file=文件路径

慢查询阈值:show variables like '%long_query_time%';
临时设置阈值:set global long_query_time=5 ----设置完毕后,重新登录后生效
永久设置阈值:修改文件,加参数long_query_time=3
mysqldumpslow工具查看慢查询。

Mysql锁机制
分类:
操作类型:读锁(共享锁)
写锁(排他锁)
操作范围:a表锁:一次性对一张表整体加锁,MySIAM,开销小,速度快,无死锁,但锁的范围大,崇义发生所冲突,并发度低。
b行锁::一次性对一条数据加锁,InnoDB.
c页锁

对表加锁:
lock table 表1 read/write
lock table tablelock read;加读锁,现在自己加的读锁不能写,读其他表也不能读,写也写不了。
其他会话能查,如果进行写操作会一直等待其他会话释放锁。

查看枷锁的表:show open tables;

MyISAM默认会自动给所有表加读锁,再进行增删改的时候会给表加写锁。
MyISAM存储引擎有一个系统变量concurrent_insert专门控制并发插入的行为,值为0,1,2
当concurrent_insert设置0时,不允许并发插入。
等于1时,允许一个读表的同时,另一个线程进行表尾插入数据,Mysql默认
等于2时,无论MyISAM表有咩有空洞,都允许再表尾插入
默认写锁的优先级比读锁的优先级高。

InnoDB锁问题
InnoDB支持事务,采用行级锁。
1.事务的ACID,原子性,一致性,隔离性,持久性
2.并发事务带来的问题
更新丢失
脏读
不可重复读
幻读
InnoDb的行锁模式及加锁方法
共享锁:允许一个事务去读一行,阻止其他事务获取相同数据集的排他锁。
排他锁:允许获取排他锁的事务更新数据,组织其他事务取得相同的数据集共享读锁和排他写锁

原创文章 41 获赞 11 访问量 1507

猜你喜欢

转载自blog.csdn.net/weixin_44038332/article/details/104994837