MySQL数据库学总结很干很有用

二叉树

MySQL数据库学总结很干很有用_第1张图片
数据的偏离度存在数据组织过程时的弊病

平衡二叉树(AVL)

AVL树是最先发明的自平衡二叉查找树,在AVL树中任何节点的两个
子树的高度最大差别为1,所以它也被称为高度平衡树
MySQL数据库学总结很干很有用_第2张图片
AVL为了保证树的平衡性,在数据的插入和删除的过程中,会进行一系列的计算.将树进行左/右旋转满足树的平衡性.可以通过数据结构模
拟的网站,进行验证.
https://www.cs.usfca.edu/~galles/visualization/AVLtree.html
既然AVL能保证树的平衡,那就解决了二叉查找树结构的线性链表问题,那么为什么MySQL并没有选择二叉结构AVL树呢?主要原因有以
下两点:

AVL的树高问题.在树形结构中,数据的所处树的位置将带来IO的
加载次数.如上图,我们需要在图中查找8的数据,我们需要进行磁
盘块1[10],磁盘块2[5],磁盘块5[8]的三次加载才能找到数据.AVL
虽然能保证平衡,但是由于是二叉树结构必然在大数据量的情况
下树高将会很高

磁盘IO的利用率问题.在前面我们已经普及到.我们的RDBMS系
统中,索引都是存储在磁盘中的.操作系统与磁盘的交互是采用页
为基本的交换单位.一页数据大小是4KB,再加上操作系统的预读
能力[空间局部性原理],一次磁盘的IO交互将会带来N页的数据返
回.但是在上图中,我们不难发现,一个磁盘块能承载的数据内容只
有一个关键字,一个数据区内容,两个子节点的指针.肯定填充不满
CSDN-Andy老师
4KB或是8KB,16KB的空间.一次低性能的磁盘IO.确只能带会仅仅
少量的有效数据.

B树 多路平衡查找树

一种绝对平衡的树形结构.他的绝对平衡指的是所有的叶子节点数据都同一个水平线上
MySQL数据库学总结很干很有用_第3张图片
优势:

将磁盘IO的低效操作通过内存中数据比较进行替换.
在二叉树中,我们一次只能加载一个关键字进行匹配.但是在B-树,
我们一次可以加载N个关键字,若我们将磁盘块(节点)的空间大小
固定(MySQL中定义为16KB).磁盘块能存储的关键字个数就会与
单个关键字内容占用的空间相关.基于预读和操作系统磁盘交互
特性.我们磁盘IO一次加载的内容正好都是我们需要比对的内容.
讲内容的多次IO加载转换成在内存中进行数据的比较
合理的降低树的高度,减少IO的次数
在树形结构中数据的所处高度位置,将带来IO的次数不一样.B-树
结构合理的降低了树的高度.也就意味着数据的IO次数将降低

B+树

MySQL数据库学总结很干很有用_第4张图片
MySQL数据库学总结很干很有用_第5张图片

相比于B树的优势

B-树拥有的特性,B+树都拥有
B+树拥有更强劲的磁盘IO能力.
在非叶子节点不存在数据区,将大大降低节点的空间占用.能存储
更多的关键字.一次磁盘IO带回来的有效数据将更多更精准
B+树拥有更好的数据排序能力
这是B+树的天然优势,在最末尾的叶子节点这一层天然即有序的
链式结构
基于B+树的扫表能力更强
在B+树的数据结构中,若需要扫表,只需要扫描最末尾的叶子节点
即可.
基于B+树结构的索引的查询,更趋于稳定
在B-树结构中,我们发现,我们的关键字在某一个节点进行匹对成
功就完成数据区内容的返回.
但是在B+树结构中,我们采用的是闭合区间的比对方式即数据的
最终加载一定会在叶子节点上. 在B-树结构中,有可能针对一张表的查询,有些数据需要3次IO.有
些只需要1次IO.前后的查询效率跌跌宕宕不稳定.但是在B+树结
构中一定恒定的IO次数,带来更稳定的查询效率

基于以上的对比和总结,MySQL最终选择了B+Tree作为了索引的数
据结构

搜索引擎

Myisam

在数据目录中,我们发现除了frm文件之外.还额外存在user_myisam.MYD 和 user_myisam.MYI两个文件.
user_myisam.MYI user_myisam表的索引文件.即该表的B+Tree索
引数据都将存储在这个文件中user_myisam.MYD user_myisam表的数据文件.即该表的数据都将存储在这个文件中
MySQL数据库学总结很干很有用_第6张图片
所以在Myisam引擎中,数据文件与索引文件是隔离存储的.在索引文件中,每一颗B+Tree树的叶子节点的数据区保存的是指向数据文件的数据行指针信息.

如果一个表存在多个索引即除了主键索引还存在额外的二级索引时
如下图
MySQL数据库学总结很干很有用_第7张图片
通过图示我们了解到MYI文件中存储的是表的索引的结构.即主键索引,辅助索引(二级索引).在Myisam引擎中,并不存在有索引的主次之分.他们是一视同仁平等的关系

Innodb

在数据目录中,我们发现Innodb类型的表只有user_innodb.frm 和user_innodb.ibd文件, frm文件我们已经介绍.是表的结构信息文件,那在Innodb中就只有一个IBD类型的文件,那Innodb中如何存储数据和索引的呢.
MySQL数据库学总结很干很有用_第8张图片
原来,在Innodb存储引擎中,数据的存储是根据主键来进行存储的.在主键索引的叶子节点层存储的并不是数据的真实磁盘指针,而是存储的当前主键代表的数据行的所有内容.如上图,若User表中有5个字段分别是,ID、name、phoneNum、email .那么在整个叶子节点的数据区存储的就是该主键代表的数据行的所有字段的信息.
这种以主键索引进行数据整理的方式,其数据的物理排序跟主键的逻辑顺序必然会保持一致.所以也主键索引在Innodb中也叫聚集(簇)索 引.且Innodb引擎中有且只有一个聚集(簇)索引.所以在Innodb类型表的数据存储就只有一个IBD文件也就能够解释了.
如果在Innodb类型的表中不仅有主键索引也包含其他的二级(辅助)索引.此时数据的搜索过程又是怎么样的呢?
MySQL数据库学总结很干很有用_第9张图片
从上图中,我们知道.在辅助(二级)索引的叶子节点上保存的数据是主键索引的值.若此时我们的查询条件是基于name的条件进行查询,首先我们会基于辅助索引的树进行一次比对和查询,查询到结果之后,拿到主键索引的值.再基于主键索引进行二次搜索进行数据的返回.这样的二次扫描的过程我们称之为回表

思考题:为什么在辅助索引的叶子节点为什么存储的是主键的值,为什么不保存数据行的指针位置呢?为什么还需要基于主键进行回表操 作?
是因为在前面的数据结构推演过程中,我们已经知道B-树,B+树,为了保证树的绝对平衡,会在数据的组织阶段进行一系列的计算和操作.如节点的合并,节点的分裂.这样的操作会带来的数据的指针位置的变化.在Innodb引擎中,一切都是以主键为基准进行设计和考量的.在我们的数据进行相应的变化之后.我们如果此时在辅助索引存储指针的话,我们势必要回头去修改所有的辅助(二级)索引叶子节点的内容

索引的优化

列的离散性

离散度计算公式: count(distinct colName) /count(colName) 比值越大离散性越好
离散性是衡量索引列选择的很重要的指标.是因为在查询的优化阶段,离散度不好的查询,优化器会自动基于成本的原本,摒弃离散性不好的索引查询.
如: select * from user where name like ‘hello-%’ 和 select * from user where name like ‘hello-123123%’

如果我们遵循了like 后面的条件 % 写在最右,但是有可能在优化器介入的阶段,由于name字段的数据绝大多数都是以’hello-'开头,导致该
列的唯一性选择很差,从而执行引擎在执行的过程中,并不使用name字段的的索引.

索引项关键字匹对规则

在索引项中关键字的匹对是从左往右依次进行.在没有强行指定数据的字符的编码排序规则时.默认采用ASCII的编码进行字符的比对.
比如:数字的比对 100 > 20
字符串的比对 “100” < “20”
“abc” < “adc”
那为什么 “abc” < “adc” 呢.首先abc 转换成ASCII编码 97 98 99 adc转换成ASCII编码 97 100 98因为在字符的比较过程中是从左至右依次进行的.所以 abc

联合索引

联合索引是多个索引么?
联合索引是一个索引,是由表字段中多列组成的索引项中关键字的一个索引.
例如.index(name) 我们索引项的关键字就是name的值.
index(name+phoneNum) 我们索引项的关键字就是name+phoneNum的值.
基于前面我们介绍的索引项关键字比对规则.故而在联合索引中有最左前缀原则.即经常使用的字段需放置联合索引的最前面.若前面的字段查询条件不存在,不能使用到中间字段的进行索引扫描. 即:带头大哥不能死,中间兄弟不能断;

联合索引与单列索引的关系?
单列索引是一种特殊的联合索引

若一个表中创建了index(name,phoneNum) 和 index(name)两个索引是否有必要?
没有必要.通过前面我们已知索引项的排序是从左到右依次进行比对的.所以index(name ,phoneNum)索引name字段的排序就包含了 index(name).所以index(name)是冗余索引

联合索引使用过程中遵循哪些原则?
最左前缀
最常使用的字段放置联合索引的前面
离散度高
离散度高的字段选择性将会更好.
最少空间

我们在选择联合索引字段时,尽量选择占用空间少的字段.避
免空间浪费.且能让我们单索引页数据能存储更多的关键字

覆盖索引

MySQL数据库学总结很干很有用_第10张图片
MySQL数据库学总结很干很有用_第11张图片

索引打油诗

全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
Like百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用。

各大存储引擎

CSV

特点:
不能定义没有索引、列定义必须为NOT NULL、不能设置自增列CSV表的数据的存储用 “,” 隔开,可直接编辑CSV文件进行数据的编排
不适用大表或者数据的在线处理数据安全性低
应用场景:
数据的快速导出导入
表格直接转换成CSV
我们可以直接通过文本工具打开CSV的数据表文件进行内容编排(满足规范),通过flush table XXX;即可完成数据的编辑

Archive

特点:
压缩协议(ARZ文件格式)进行数据的存储,磁盘占用少
只支持insert和select两种操作
只允许自增ID列建立索引
应用场景:
日志采集系统
大量设备数据采集及归档
MySQL数据库学总结很干很有用_第12张图片

Memory

特点:
数据都是存储在内存中,处理效率高,表大小限定默认16M
不支持大数据存储类型的字段 如 blog,text
支持Hash索引,等值查询效率高
字符串类型强制使用char 如varchar(32) --> char(32)
数据的可靠性低,重启或系统奔溃数据丢失

应用场景:
数据热点快速加载
查询结果内存中的计算,大多数都是采用这种存储引擎作为临
时表存储需计算的数据

Myisam

特点:
较快的数据插入和读取性能
较小的磁盘占用[相较于Innodb]
支持表级别的锁,不支持事务
数据文件与索引文件分开存储[MYD和MYI]
Myisam的统计count方法可以是通过额外的常量进行返回

应用场景:
只读应用或者以读为主的业务
MySQL5.1版本之前默认存储引擎是Myisam

Innodb

支持事务
行级锁
聚集索引
数据行内容与索引结构在一个文件[IBD]
外键支持,保证数据的完整性

应用场景:
无脑选择
MySQL5.5及版本及之后的MySQL默认存储引擎

一条SQL执行的五个流程

MySQL数据库学总结很干很有用_第13张图片
我们把SQL执行的整个流程分为5个阶段.分别为
C-S的通讯阶段
查询缓存阶段
SQL验证和优化阶段
执行引擎执行阶段
数据返回阶段

执行计划

如何得到执行计划

MySQL数据库学总结很干很有用_第14张图片

执行计划详解

select查询的序列号,包含一组数字,表示查询中执行select子句或
操作表的顺序
1、id相同:执行顺序由上至下
2、id不同:如果是子查询,id的序号会递增,id值越大优先级越
高,越先被执行
3、id相同又不同(两种情况同时存在):id如果相同,可以认为是
一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行

select_type
查询的类型,主要是用于区分普通查询、联合查询、子查询等复杂
的查询
常见的取值
Simple 简单查询(普通查询)
PRIMARY 最外层查询
SUBQUERY 子查询
UNION 连接查询
UNION RESULT 连接查询的结果集

table
查询涉及到的表或者表的别名
常见取值
表名或者取的别名
查询id为M和N2个结果集进行并集结果
派生表查询id为N的结果集
派生表是从select语句返回的虚拟表。派生表类似于临时表,但是在SELECT语句中使用派生表比临时表简单得多,因为它不需要创建临时表的步骤。所以当SELECT语句的FROM子句中使用独立子查询时,我们将其称为派生表 id为N子查询的结果列表

partitions
查询将从中匹配记录的分区。该值适用NULL于未分区的表

type
数据获取的方式.SQL查询优化中一个很重要的指标,他是评测SQL好坏最直观的参数.
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types
system > const > eq_ref > ref > range > index > ALL 一般来说,好的sql查询至少达到range级别,最好能达到ref

system
表只有一行记录(等于系统表),这是const类型的特例,平时
不会出现,可以忽略不计.
const
表示基于唯一性索引(主键或者唯一索引)唯一性条件为常数的比较
eq_ref
唯一性(主键,唯一)索引的扫描
ref
普通索引的扫描 等值查询
range
扫描给定索引的范围行,一般在where语句中出现了bettween、 <、>、in, like 等的查询。这种索引列上的范围扫描比全索引扫描要好,只需要开始于某一行,结束于某一行,不用扫描全部索引
index
Full index Scan , 全索引扫描,这种类型只需要扫描索引树. (Index与ALL虽然都是读全表,但index是从索引中读取,而ALL是从表中读取)所需要扫描的数据体量要少于all
all
Full Table Scan, 全表扫描,匹配数据行

possible key
可能使用到的索引
key
真正使用到的索引.如果取值为NULL.则没有使用索引
key_len
标识使用到的索引列长度.
计算公式:
varchr(10) 变长字段且允许NULL = 10 * (utfmb4=3utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
varchr(10)变长字段且不允许NULL = 10 (utfmb4=3utf8=3,gbk=2,latin1=1)+2(变长字段)
char(10)固定字段且允许NULL = 10 * (utfmb4=4utf8=3,gbk=2,latin1=1)+1(NULL)
char(10)固定字段且不允许NULL = 10 * (utfmb4=4utf8=3,gbk=2,latin1=1)
rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
filtered
它指返回结果的行占需要读到的行(rows列的值)的百分比表示返回结果的行数占需读取行数的百分比,Filter列的值越大越好,表示扫描数据的准确性很高.比如 rows为1000,filtered值为50 则真正返回的数据为500行
Extra
Using filesort MySQL对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取也就是说MySQL无法利用已有索引成的排序操作所以使用文件排序方式
Using temporary
使用临时表保存中间结果,也就是说mysql在对查询结果排序时使用了临时表,常见于 group by操作
Using index
表示相应的select操作中使用了覆盖索引(Covering Index),避免了访问表的数据行,效率高
Using where
使用了where 后面的条件进行过滤
select tables optimized away
基于索引优化MIN/MAX操作或者MyISAM存储引擎优化COUNT(
)操作,不必等到执行阶段在进行计算,查询执行计划生成的阶段即可完优化

Innodb Transaction

事务的支持

事务指的是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,事务是一组不可再分割的操作集合(工作逻辑单元)

事务的四大特性及实现

原子性(Atomicity) 事务是数据库操作的最小工作单元,整个工作单元要么一起提交成功,要么全部失败回滚
一致性(Consistency) 事务中操作的数据及状态改变是一致的,即写入资料的结果必须完全符合预设的规则,不会因为出现系统意外等原因导致状态的不一致
隔离性(Isolation) 一个事务所操作的数据在提交之前,对其他事务的可见性设定(一般设定为不可见)
持久性(Durability) 事务所做的修改就会永久保存,不会因为系统意外导致数据的丢失

MySQL数据库学总结很干很有用_第15张图片

隔离级别的实现主要两大技术

LBCC
Lock Based Concurrency Control(LBCC),事务开始操作数据前,对其加锁,阻止其他事务对数据进行修改针对SQL的操作,使用当前读解决并发读写的隔离性问题
MVCC
Multi Version Concurrency Control(MVCC),事务开始操作数据前,将数据在当下时间点进行一份数据快照(Snapshot)的备份,并用这个快照来提供给其他事务进行一致性读取 并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理。避免写操作的堵塞,从而引发操作的并发阻塞问题,使用快照读解决并发读写的隔离性问题

Innodb锁机制详解

对比表级别锁行级别的锁具有以下优势:
锁定粒度:表锁 > 行锁 加锁效率:表锁 > 行锁 冲突概率:表锁 > 行锁 并发性能:表锁 < 行锁

Innodb的锁分类

共享锁(行锁):Shared Locks
读锁(S锁),多个事务对于同一数据可以共享访问,不能操作修改
使用方法:
SELECT * FROM table WHERE id=1 LOCK IN SHARE MODE –
加锁 COMMIT/ROLLBACK – 释锁
排他锁(行锁):Exclusive Locks
写锁(X锁),互斥锁/独占锁,事务获取了一个数据的X锁,其他事务就不能再获取该行的锁(S锁、X锁),只有该获取了排他锁的事务是可以对数据行进行读取和修改.
使用方法:
DELETE/ UPDATE/ INSERT – 加锁 SELECT * FROM table WHERE … FOR UPDATE – 加锁 COMMIT/ROLLBACK – 释锁
意向共享锁(表锁):Intention Shared Locks & 意向排它锁 (表锁):Intention Exclusive Locks
意向共享锁(IS) 一个数据行加共享锁前必须先取得该表的IS锁,意向共享锁之间是可以相互兼容的 意向排它锁(IX) 一个数据行加排他锁前必须先取得该表的IX锁,意向排它锁之间是可以相互兼容的 意向锁(IS、IX)是InnoDB引擎操作数据之前自动加的,不需要用户干预 意义: 当务操作需要锁表时,只需判断意向锁是否存在,存在时则可快速返回该表不能启用表锁

Innodb的行锁实现

InnoDB的行锁是通过给索引上的索引项加锁来实现的
Innodb按照辅助索引进行数据操作时,辅助索引和主键索引都将锁定指定的索引项
通过索引进行数据检索,InnoDB才使用行级锁,否则InnoDB将使用表锁

Innodb的行锁实现具体的算法

临键锁 Next-key Locks
间隙锁 Gap Locks
记录锁 Record Locks

LBCC 与 MBCC 详解

https://blog.csdn.net/weixin_43843797/article/details/86479184

你可能感兴趣的