cyc大佬有地方写的不全,补充(数据库篇)
一.索引
1.B树,B+树,以及两者的区别
B树是一种多路平衡查找树,其每一个节点都存储Key和data
B+树是B树的一个变种,叶子节点存储data,非叶子节点只存储key,B+树的叶子节点增加了顺序访问指针,每一个叶子节点都可以访问到他的下一个叶子节点
区别:
1.B+树种只有叶子节点会带有全部信息,非叶子节点只起到索引的作用,二B树的所有节点都带有全部信息,B+树的每一层节点都会再次出现在下一层节点上
2.B+树种所有叶子节点都是通过指针连在一起,B树则没有
2.索引的优点和缺点
优点:可以加大检索速度
缺点:创建和维护索引需要耗费时间
3.Mysql为什么选择B+树
Mysql数据本质上是放在外部存储的,B+树是为了加快读取速度二设计的一种数据结构
1.可以减少i/o次数,只有叶子节点才存储数据,非叶子节点存储索引,这样一次读取到内存的关键字增多,相对i/o次数也就减少(根据区别一)
2.能够提供稳定高效的范围扫描,因为所有的叶子节点都互相连接(根据区别二)
4.索引越多越好吗?
索引可以提高select的效率,但是也降低了insert和updata的效率,因为插入和更新的时候可能会重建索引,索引怎么建索引要慎重考虑。
5.索引分类
1.B+树索引:以b+树作为数据结构的索引
2.hash索引:能以O(1)的时间复杂度查找,但失去了有序性,innodb有一个自适应哈希索引,当这个索引值被频繁使用时会在b+树上创建一个哈希索引
3.全文索引:用于查找文本的关键词,中文需要由中文分词插件
二. MySQL优化
一.MySQL的优化,主要分为索引的的优化,sql语句的优化,表的优化。同时可以使用缓存增加效率
1.索引的优化
只要列中含有null,最好不要再此列设置索引
对于经常在where语句中使用的列,最好设置一个索引
对于like语句,以%或者-开头的不会使用索引,以%结尾会使用索引
二.sql语句的优化
查询优化要尽量避免全表扫描
查询时能不用*就不用*,尽量写字段名
三. MySQL常问问题
1.数据库如何应对大规模的写入和读取
(1)使用NoSQL,通过降低数据的安全性,减少对事物的支持,减少复杂查询的支持来获取性能的提升;但有些场合NoSQL无法满足要求
(2)分库分表:
水平切分:不修改数据库的表结构,通过对表中的数据拆分而达到分片的目的,一般水平切分在查询的时候可能会用到union操作(多个结果并)
可以根据hash或者日期来进行分表
垂直切分:修改表结构,按照访问的差异将某些列拆分出去,一般查询数据的时候可能会用到join操作;把常用的字段放在一个表中,不常用的放在一个表中;把字段比较大的比如text字段拆出来放在一个表中。
分库:分表能够解决数据量过大带来的查询效率下降问题,但是却无法给数据库的并发处理能力带来质的提升;分库可以对关键字取模的方式来对数据访问进行路由;
(3)读写分离:
读写分离是在主服务器上修改数据,数据也会同步到从服务器上,从服务器只能提供读取,不能写入,实现备份的同时也实现了数据库的性能优化
如何保证数据一致性:
(1)主节点
保证事务每次提交之后,要确保binlog都能刷新到磁盘中,只要有了binlog,innoDB就有方法恢复数据,不至于导致主从复制的数据丢失
(2)从节点
开启 relay log 自动修复机制,发生 crash 时,会自动判断哪些 relay log 需要重新从master 上抓取回来再次应用,以此避免部分数据丢失的可能性。
2.数据库事务及其隔离级别
事务的特性:ACID
事务在并发的时候,隔离性很难保证主要可能出现下面这些问题:
脏读:一个事务读了另外一个事务未提交的数据,如果另一个事务回滚则会发生脏读
不可重复读:一个事务前后读取同一行数据,如果在这个过程中有其他事务修改了此数据则会发生不可重复读
幻读:一个事务前后读取范围的时候
事务隔离级别:
MySQL实现事务是基于undo/redo日志实现的:
undo日志记录修改前的状态,ROLLBACK基于UNDO日志实现;
REDO日志记录修改后的状态,事务的持久性基于REDO日志实现
两种解决脏读、不可重复读、幻读的方案:
MVCC(性能较高,但读的可能是历史版本)
1.版本链:对于每一行的数据,在undo日志中,总会记录每个版本记录以及对应的事务id,
2.readView:
核心问题:当前版本链中哪个版本对当前事务可见
Readview包含的内容:{当前活跃的事务id,下一个应该分配的事务id,当前自己的事务id},根据当前读的版本事务id和这个readview对比,如果是活跃的或者大于下一个应该分配的事务id则说明当前版本对此事务不可见,应该前读一个版本,依次类推直到找到可见的版本
提交读:每次读取数据前都会生成一个readview
可重复读:在第一次读取时句时生成一个readview
锁(性能不高,但读的是最新版本):
MyISAM和innoDB的区别
1.innodb支持行锁,myisam不支持行锁
2.innodb支持事务,myisam不支持事务
3.innodb支持回滚和安全回复,myisam不支持
4.innodb的索引就是数据,myisam的索引只存储了主键和行号,还需要根据行号去查找相应的记录
5.innodb更适合写密集的表,myisam更适合读密集的表