内容参考:《高性能Mysql 第三版》 《Mysql是怎样运行的:从根儿上理解Mysql》这本书作者是
“小孩子” 掘金上有在售,作者微信公众号:我们都是小青蛙
Mysql的事务隔离级别:
1.READ UNCOMMITE
该隔离级别事务之间可以读取到其他事务未提交的数据,即为dirty read
2.READ COMMITTED
读取其他事务提交的事务,也就是该事务开启之后到提交之前的操作对其他事务
都是不可见的,也成为不可重复读
3.REPEATABLE READ
可重复读,解决了脏读,该级别保证了在同一个事务中多次读取同样的记录的结果是
一致的,但是理论上,可重复读还是无法解决幻读的问题,所谓幻读:指的是当某个
事务读取某个范围的记录时另一个事务又在该范围内插入了新的数据,幻读就是每次
读取的数据可能不一样,这个级别是Mysql的默认隔离级别,其它多数数据库的隔离
级别是READ COMMITTED
4.SERIALIZABLE
串行化读取,是事务隔离的最高级别,强制事务串行执行,在读取数据的每一行加锁
可能导致大量的超时和争锁问题,只有在非常需要确保数据一致性而且可以接受没有
的情况下采用这种隔离级别
Mysql数据的存储:
存放用户记录的数据页,存放目录项的数据页 都是16K,我们的实
际用户记录其实都存放在B+树的最底层的节点上,这些节点也被称为叶子节点或叶节点,
其余用来存放目录项的节点称为非叶子节点或者内节点,其中B+树最上边的那个节点也称
为根节点。
B+树的节点即页(数据页)
页内的记录按照索引从大到小的顺序组成一个单项链表
各个存放用户记录的页也是根据页中用户记录主键大小排成双向列表
存放目录项的页,也根据目录项记录的主键大小排成双向列表
页表之间双向链表连接,页表内的目录项/记录项按照主键排成单向链表
聚簇索引:
InnoDB存储引擎会自动的为我们创建聚簇索引。另外有趣的一点是,在InnoDB存储引擎中,
聚簇索引就是数据的存储方式(所有的用户记录
都存储在了叶子节点),也就是所谓的索引即数据,数据即索引。
InnoDB的B+树索引适用的条件(匹配原则)
1.建立索引其实就是对以该索引的值对记录进行排序,联合索引是按照给出的索引的顺序
依次排序,比如给a b c三个字段建立联合索引,先按照a排序a相同的情况下按b排序b相同
则按照c排序,SELECT * FROM EMP WHERE a = * AND c = *那么只会走a索引,因为
B+树叶子节点存储的用户记录是依照a、b、c依次排序的,在a相同的情况下直接查找c的
匹配条件是做不到的,因为a相同时b的值可能时无序的,对不起,臣妾做不到!所以当
建立了联合索引后必须至少包含最左侧索引,要不然所有的索引是失效的,但是索引是一把
双刃剑,虽然提交了查询的效率,但是每个索引都对应一颗B+树,索引建立的越多,引擎
维护的数据就要越多,明显就是拉跨,为什么这么说:因为索引每棵树的页节点之间是按照
索引的值进行排序组成的双向链表,而每个页中,无论是目录项还是记录项都是以索引值排序
组成的单向链表,对表的增删改都可能会导致页面分裂,页面回收,索引偏移,这就是维护
索引要付出的代表,也是系统的开销所在
有一条原则:以最左匹配的原则进行范围匹配只有在上一个所以匹配的情况下才可以使用下级
一个规则例如在name一样的情况下还可以走age索引,但是以name查询出的结构age可能是
无序的,所以不会走age索引
......
为用于搜索、排序或分组的列创建索引。如果索引列在比较表达式中不是以单独列的形式出
现,而是以某个表达式,或者函数调用形式出现的话,是用不到索引的。
我们知道,对于一个使用InnoDB存储引擎的表来说,在我们没有显式的创建索引时,表中的
数据实际上都是存储在聚簇索引的叶子节点的。而记录又是存储在数据页中的,数据页和记
录又是按照记录主键值从小到大的顺序进行排序,所以如果我们插入的记录的主键值是依次
增大的话,那我们每插满一个数据页就换到下一个数据页继续插,而如果我们插入的主键值
忽大忽小的话,这就比较麻烦了。数据页已经满了,再插进来咋办呢?我们需要把当前页面
分裂成两个页面,把本页中的一些记录移动到新创建的这个页中。页面分裂和记录移位意味
着什么?意味着:性能损耗!所以如果我们想尽量避免这样无谓的性能损耗,最好让插入的
记录的主键值依次递增,这样就不会发生这样的性能损耗了。所以我们建议:让主键具有AU
TO_INCREMENT,让存储引擎自己为表生成主键,而不是我们手动插入
注:扫描聚簇索引 即 全表扫描
主键索引
有主键的表在表创建之后就会为其创建索引,如果想使用主键意外的字段作为索引,那就需要
额外的创建索引,即二级索引,二级索引在创建之后根页面什么也没有,当插入数据之后达到
可存储的记录上限后页面分裂,产生出新的页,原来的根页中就保存索引 + 主键 + 值,这个
其实就是建树的过程
在InnoDB中索引即数据,数据即索引,而MyISAM中索引时索引,数据是数据
MyIsam引擎关于索引的问题
首先MyIsam会将索引和数据分离,记录会以插入顺序存储在数据文件中,索引的叶子节点
存储的并不是完整的用户数据,而是主键和行号
与InnoDB索引不同的地方在于Inno的B+叶子节点中会存放记录的完成数据,而MyI只存储
主键和页号,查询的时候需要根据主键确定行号,然后依据行号回表查询。因为MyIsam采用
的时定长行格式static (还有Dynamic、Compressed),这样每条记录的大小都是固定的,就
可以轻松算出每条记录在数据文件中的偏移量,MyISAM会在叶子节点处存储该条记录的偏移量
注:如果为每个字段创建索引,需要维护大量数据之间的排序关系,很消耗性能和存储空间
关于索引的总结
上边只是在创建和使用B+树索引的过程中需要注意的一些点
1.B+树索引在空间和时间上都有代价,所以没事儿别瞎建索引。
2.B+树索引适用于下边这些情况:
全值匹配
匹配左边的列
匹配范围值
精确匹配某一列并范围匹配另外一列
用于排序
用于分组
3.在使用索引时需要注意下边这些事项:
1.只为用于搜索、排序或分组的列创建索引
2.为列的基数大的列创建索引,基数:数据的离散程度,越离散越适合
3.索引列的类型尽量小,以整形为例TINYINT、MEDIUMINT、INT、BIGINT,能使用TINYINT就不使用
MEDIUMINT,因为索引是存在B+树中的,占用空间越少,那么每次读入内存的数据页中目录项就越
多,那么一次可处理的记录数就越多。(InnoDB的数据也大小为16k)
4.可以只对字符串值的前缀建立索引
5.只有索引列在比较表达式中单独出现才可以适用索引
6.为了尽可能少的让聚簇索引发生页面分裂和记录移位的情况,建议让主键拥有AUTO_INCREMENT属性。
7.定位并删除表中的重复和冗余索引
8.尽量使用覆盖索引进行查询,避免回表带来的性能损耗。