这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
Mysql复习--索引
哪些场景下应该使用自增主键,而哪些场景下不应该?
给个结论,一般情况下都是加个自增主键比较好。为什么呢?
首先我们得知道的是,Mysql是索引组织表,也就是根据主键顺序以索引的方式创建的表。而且索引上采用的数据结构是B+树,在插入新值时就得维持索引的有序性,而如果我们插入的值没有顺序的话,那就不可避免地会出现数据页分页的情况,而正是在这里,数据库会需要申请一个新的数据页,然后把原来的数据移一部分数据到这个新数据页上,这个过程肯定就会带来一定量的性能损耗,而且还有一个副作用,那就是数据页的分页会导致数据页的资源利用率下降(Mysql里面也有这个的逆过程,当数据页利用率很低时会合并回来),进而导致的就是空间的浪费,所以使用自增主键可以很有效的解决这个问题。 还有一个角度去理解是,如果我们将一个长度很长的值做为主键,当我们给其它列加索引时,而我们的非主键索引的叶子结点的内容正是主键的值,这样又会导致内存的浪费。
所以还是加个自增主键吧
普通索引和唯一索引的区别
当我们业务代码在前面能保证一个字段是唯一的情况下,对这个字段使用普通索引和唯一索引在逻辑上都是可以的。
事实上在查询上确实差别不大,唯一索引根据索引快速找到结果后便可以返回了,普通索引也是根据索引快速找到结果返回,但不同的是普通索引还得再进行一次判断,判断下一个值是否符合条件,不符合就可以结束这次查询了(因为前面已经保证唯一的了,所以肯定是到这判断一次就结束了),所以两者在查询上差别就是这一下判断了,其实这一下判断也用不了多少资源,所以两者在查询上的区别可以忽略不计。 更新上才有很大的区别,对于唯一索引来说,当插入一个值时,如果当前内存中恰有对应的数据页,那就直接判断,然后更新就行了,而如果内存中没有,则把就必须从磁盘中读出对应的数据页,然后再判断再更新。而普通索引在这个地方和唯一索引却有很大不同,它用到了change buffer这个东西,如果当前内存中有对应的数据页的话,那就和唯一索引一样,直接在内存中更新就好了,甚至都没有判断这一步骤,而如果内存中没有的话,它就会把更新操作写到 change buffer 中,然后就结束更新了,之后 change buffer中的操作会在我们下一次进行查询,把数据页读到内存时给应用上去,这一过程叫做merge。
对于change buffer的理解:
引用:很多同学这里纠结为什么change buffer要持久化到 共享表空间 又要保存到redolog里。 ok,这里我
们假设不把change buffer保存到redolog里,就只持久化到 共享表空间里, 那么在修改非唯一不在内存的
二级索引时,我们要把这个修改记录生成一份change buffer, 并且在这个时候需要立即马上将这个内从中的
change buffer持久化到共享表空间中,以防止 这个时候数据库宕机,内存中的change buffer丢了,所
以,在不引入redolog的情况下, 生成的change buffer需要立即马上进行持久化至共享表空间中,这是一次
随机io,可开销不小。 这个时候你就要想想有什么办法能把这个随机io写变成顺序io写呢,或说者不要立刻
随机io写, 而是先顺序写,等数据库不忙的时候在来随机写呢?这个肯定就是redolog的活了。 到了这里,
我们发现需要引入redolog了,来吧这个change buffer的随机io写持久化延后。 我们带入redolog再来重新
模拟下,修改改非唯一不在内存的二级索引的例子。 数据修改后生成change buffer,这个时候我们立刻马上
把这个change buffer保存至redolog里, 然后就万事大吉了,即使数据库宕机,这个change buffer也能被
找回来,在此刻一共有在内存中 有一份change buffer在redolog中也有一份change buffer,如果后台线程
这个时候把change buffer 持久化到了共享表空间中,那么会推进checkpoint,redolog里的存的change
buffer就没用了,就算 宕机恢复也会从保存change buffer之后的redolog开始恢复,change buffer就已
经持久化到 共享表空间中,不需要redolog了。
在加一张图片:
也就是说redo log在入盘时并不会去操作数据的更新,因为它根本不知道怎么更新,它只是有对change buffer的修改记录,而change buffer中记录的才是真正的修改。它在下一次读取到这个数据时才会去修改,