MySQL优化
MySql-思维导图
一.索引的概述
1.为什么要使用索引
在海量数据中提升性能需要要看查询的字段是否有索引关系,加索引查询新能快
2.索引是什么
查字典的方式>通过目录快速定位到目标所在的页码
没用索引时:
使用索引
3.索引存放位置
C:\ProgramData\MySQL\MySQL Server 8.0\Data\library@002dmanager@002dsystem
-
.ibd索引和数据
-
.MYD数据
-
.MYI索引
InnoDB存储引擎:将索引和数据放在同个文件下
MyISAM存储引擎:将索引和数据放开两个文件存储
3.索引的分类和创建
- 主键索引
主键自带索引,通过主键查询 表中的记录,性能是非常好的
- 普通索引
create index 索引名称 on 表名(列名)
create index idx_bid on book(book_id)
- 唯一索引
在普通索引基础上,列的值时唯一的
create unique index idx_bname on book(book_name)
- 联合索引
在一个索引中包含了多个列
create index idx_bauthor_bpublish on book(book_author,book_publish)
- 全文索引
搜索引擎是用到.不会用MySql做全文索引,只有MyISAM支持
二.数据结构
1.线性表
顺序表存储结构,链式存储结构,单向链表,双向链表
- 单向链表
- 双向链表
2.栈和队列
顺序栈,链栈,顺序队列,链式队列
- 栈
- 队列
3.串
定义串,动态串
4.数组和广义表
- 广义表:表中可以放具体的元素,也可以放另外一张表,类似多维数组,比多维数组节省空间
-
满二叉树:都放满了
-
完全二叉树:排序树,先放左边
-
二叉排序树:左边的节点值小于右边的
-
平衡二叉树(AVL树):每棵树的左子树与右子树深度不超过一,每颗子树也是平衡二叉树,查找性能是最好的
转换:
右旋:
左旋:
双向旋转:
练习网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
- 红黑树:
红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:
-
性质1:每个节点要么是黑色,要么是红色。
-
性质2:根节点是黑色。
-
性质3:每个叶子节点(NIL)是黑色。
-
性质4:每个红色结点的两个子结点一定都是黑色。
-
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
红黑树并不是一个完美平衡二叉查找树,从图1可以看到,根结点P的左子树显然比右子树高,但左子树和右子树的黑结点的层数是相等的,也即任意一个结点到到每个叶子结点的路径都包含数量相同的黑结点(性质5)。所以我们叫红黑树这种平衡为黑色完美平衡。
- B树
一个节点可以存放多个数(节点的度)
如果节点度比较大,,那么存放的数据节点的个数就比较多,那么整棵树的深度就比较浅,整颗树的查询性能就很好
- B+树
-
hash表
查找性能比B+树好,但不支持区间访问
6.图
连通图,有向图
三.InnoDB和MyISAM的区别
MyISAM:非聚集索引
支持全文检索,支持表锁
InnoDB:聚集索引
普通索引
冗余放相同数据会造成空间浪费
推荐主键整型自增,不规律的主键会造成多次自旋影响性能
如果忘记了创建主键,MySQL也会创建临时主键
四.联合索引
存储:一个索引存储了多个列
create index idx_bauthor_bpublish on book(book_author,book_publish)
最左前缀法则:
创建了联合索引以后,在使用SQL查询时,能否命中索引,就看查询条件是否遵循了
最左前缀法则.就不会全表扫描
联合索引是name和age,查询条件一定要包含name,遵循左前缀,就能走索引
table列
- 表示该SQL正在访问那张表,也可以看出正在访问的衍生表
type列
可以看出SQL查询性能从大到小排列
null>system>const>eq_ref>range>index>All
- null 查询时使用了聚合函数,直接从索引树里获取数据,不查表
explain select min(id) from tb_book;
-
const 进行查询时,使用了主键或者唯一索引值与常量比较
-
system 是const的特殊情况,在衍生表里,直接匹配一条记录
-
eq_ref 在进行连接查询时,连接的查询条件中使用了本表的主键进行关联
explain select * from tb_book_author left join tb_book on tb_book_author.book_id=tb_book.id;
- ref 进行连接查询时,连接查询的条件中使用了本表的联合索引列
explain select book_id from tb_book left join tb_book_author on tb_book.id=tb_book_author.book_id
- range 索引列上使用了范围查找
explain select *from tb_author where id>1
- index 在查询表中的所有记录,所有的记录可以直接从索引树上获取
explain select * from tb_book
id和name时索引列
- ALL 全表扫描
id列 SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
在查询结果中,多条sql语句,谁的id大,谁先执行,若果多条sql语句一样大,谁在上面谁执行
possible_keys列
第一次查询可能用到的索引
如果使用索引查找的性能并没有全表扫描好,内部优化器会选择全表扫描
explain select *from employees where name 'like custome%'
key列
内部优化器最终选择是否使用索引来进行查找
key_len列
通过查看这一列的数值,推断出本sql选择了联合索引的那几列
影响索引长度因素:
-- 1. 索引列为字符串类型的情况
-
列长度:
-
列是否为空: NULL(+1),NOT NULL(+0)
-
字符集: 如 utf8mb4=4,utf8=3,gbk=2,latin1=1
-
列类型为字符: 如 varchar(+2), char(+0)
计算公式:key_len=(表字符集长度) * 列长度 + 1(null) + 2(变长列)
extra
- using index 使用了索引覆盖
- using where
mysql事务(内存):
-
原子(本次事务不能参杂其他事务,独立,唯一)
-
持久(内存写到硬盘)
-
一致
-
隔离(在内存里保证数据不被别人读取)
隔离
- 读未提交:---->脏读
2.读已提交:---->解决了脏读 出现不可重复读 oracle默认
- 可重复读 ---> 解决了脏读 和 不可重复读 mysql默认
读之前读的数据
- 序列化读:--->锁全表,我读时别不能读