目录
一、引言
本篇文章将对MySQL中的一些重点知识进行学习以及了解。
二、SQL基础
1.NOSQL和SQL的区别
SQL代表关系型数据库,意味着这样的数据库是以二维表的形式将数据进行存储,有字段,字段有一定的数据,NOSQL的典型代表就是Redis这样的数据库,他并不是按照二维表这样的形式存储数据,而是类似哈希这样的键值对进行存储,当然还有很多非关系型数据库,是通过其他的数据结构进行数据存储的。
但是NOSQL这样的数据库比较容易进行扩展,能够基于自身的业务进行特定的扩展,而mysql这样的关系型数据库扩展就很难了。
2.数据库三大范式
1.数据库的每一列都不能进行分割,一个字段不能存多个数据
2. 每一个字段都必须和主键的字段有所关联
3.每一个字段不能与其他非主键字段进行关联
3.Mysql有哪些联表查询
1.内连接
返回两个表有匹配关系的行
2.(左,右)外连接
返回左表或者右表的全部内容以及另外一张表匹配的内容
3.全外连接
返回两个表中所有的行,包括非匹配行,full join需要使用union来实现
4.char和varchar的区别
char是固定长度的字符串类型,在定义的时候需要指定固定长度,存储时会在末尾补足空格,对于短字符串来说效率更高,适合于对于定长的字符串
varchar是可变的字符串,定义时要指定其最大的长度。适合于用户输入的文本等不确定长度的场景。注意:varchar(255)这里的255代表的是字符,而不是字节。
5.外键约束
外键约束最主要的作用就是确保数据的完整性和一致性。
6.如何用MySQL实现一个可重入的锁
加锁逻辑:
1.开启事务
2.执行一条查询sql,判断这个锁有没有被占有,如果没有就直接插入,有判断是否是同一个线程,是的话就直接进行重入,并修改重入的次数。
3.提交事务
解锁逻辑:
1.开启事务
2.执行一条查询sql,判断记录是否存在,如果记录存在,且持有者是同一个线程,则重入数-1
重入数小于等于0之后就完全释放锁
3.提交事务
三、存储引擎
1.执行一条SQL请求的过程是什么
连接器:连接sql和客户端,建立连接,管理连接、校验用户身份;
Server层:
查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;
解析SQL:通过解析器对SQL的语句进行解析,提取SQL语句的关键字和非关键字,判断SQL语句是否真的存在
执行SQL:1.预处理阶段:判断表和字段是否存在。2.优化阶段:执行器会自行去选择最合适,最好的查询方式。3.执行阶段:按照之前所设定的执行,从存储引擎中读取数据,返回给客户端
2.Mysql的存储引擎,你了解吗
1.InnoDB:InnoDB是默认的存储引擎,具有ACID的特性,同时也支持行级锁,外键约束这样的特性,适合于高并发的读写操作
2.MyISAM:不支持ACID这样的性质,比较适合用于读多写少的场景,在并发写和数据完整性这一块有缺陷,因为其不支持ACID也不支持行级锁和外键约束
3.Memory:将数据存储在内存中,适用于对性能要求较高的读操作,但是在服务器重启或崩溃的时候会导致数据的丢失。同时其也不支持ACID,行级锁,外键约束这样的性质。
3.Mysql为什么默认是InnoDB这样的存储引擎
因为InnoDB提供了外键约束,行级锁,ACID这样的性质
事务支持:可以进行ACID属性的操作。
并发性能:采用了行级锁定的机制,可以提供更好的开发性能,MyISAM存储引擎只支持表锁,所得粒度比较大
崩溃恢复:InnoDB引擎通过redolog日志实现了崩溃恢复,可以在数据库发生异常的时候通过日志的方式恢复数据,保证了数据的一致性和持久性。
4.说说聚簇索引和非聚簇索引
我个人理解聚簇索引就是主键索引有没有和数据放在一起,索引InnoDB这样的存储引擎下就必须存在主键,主键的索引存储在叶子节点中,其他的索引就是辅助索引,先查询到主键,再通过主键去查询到数据。所以主键不应过大,因为主键很大,其他索引也会很大。
注意:主键索引的叶子节点存放的是主键和实际的数据,二级索引的叶子节点存放的是主键值,而不是实际数据,如果查询的数据能在二级索引中查询到,那么就不需要回表,这个过程就是覆盖索引,如果不在二级索引中,就先检索二级索引找到对应的主键值,再进行主键查询,这就是回表。
回答的时候可以从 数据存储 ,索引和数据的关系, 唯一性, 效率这四个方面回答。
数据存储:聚簇索引的数据和索引存储在一起都是存储在叶子节点上,非聚簇索引的叶子节点存储的是主键信息或指向数据行的指针。
索引与数据的关系:通过聚簇索引查找数据的时候,因为索引和数据紧密挨在一起,所以可以直接从索引中获得数据,但是非聚簇索引得先找到主键值,通过主键值回溯到聚簇索引查找实际的数据行,这就是”回表“。
唯一性:聚簇索引也就是主键是唯一的,但非聚簇索引可以有多个。
效率:在范围查询和排序查询的时候,聚簇索引的效率更高,因为它避免了额外的寻址开销,但是非聚簇索引在进行覆盖索引的时候效率更高,因为它不需要读取完整的数据行,但如果要进行回表操作,那么聚簇索引的效率会更高。
聚簇索引:1.如果有主键就以主键为聚簇索引。2.没有主键,就选择第一个不含null值的唯一列成为聚簇索引。3.上面两种都没有的情况下,InnoDB会自动生成一个隐式的自增id来作为聚簇索引。
5.InnoDB和MyISAM的区别
1.事务:InnoDB支持事务,MyISAM不支持事务
2.索引:InnoDB是聚簇索引,而MyISAM是非聚簇索引
3.锁的粒度:InnoDB支持行级锁,能够将某一行的数据给加锁,MyISAM只支持表级锁
4.count的效率:innoDB执行count命令的时候回去全盘扫描这一整张表,而MyISAM有一个变量去存储整个表的行数,所以效率较高。
四、索引
1.索引的作用
索引类似于书籍的目录,作用就是降低查找的时间,提高查找效率,如果没走索引的话,时间就是O(N),如果走了索引,时间就是O(logDN),D代表节点允许的最大子节点数
2.索引的分类
数据结构分:B+索引,哈希索引等
物理存储分:聚簇索引,非聚簇索引
字段特性分:主键,唯一,普通,前缀,全文
字段个数分:单列,联合
联合索引就是将多个字段组合在一起形成一个索引,先按某个字段进行比较,在第一个字段相同的情况下再按其他字段进行比较。
这时候联合索引就会引出一个原则:最左匹配原则:按照最左匹配优先的方式进行索引匹配,如果不遵循最左匹配原则可能会导致联合索引失效。
范围查询:范围查询的字段可以用到联合索引,但是在范围查询字段的后面的字段无法用到联合索引
3.Mysql的索引是如何实现的
通过B+树来实现的,这得益于B+树的数据结构,B+树是一个多叉树,每一层父节点的索引值都会出现在下层节点的索引值,叶子节点存储了所有的主键索引信息,并且每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。
B+树存储千万级的数据只需要3-4层高度,这意味着操作这千万级的数据只需要3-4次磁盘I/O,相较于B树和二叉树来说,最大的优势在于查询效率更高。
4.B+树的特性
1.所有叶子节点都在同一层:确保所有的数据项的检索都具有相同的I/O延迟,提高了效率,并且每个叶子节点都有与其相邻节点的指针,形成了一条链表,这样就比较适合于范围查询和排序扫描,可以沿着这条链表进行数据访问
2.非叶子节点都存储索引键值:由于非叶子节点只存储索引和指向子节点的指针,当数据量比较大的时候,相对于B树来说,B+树的高度就会较低,查找效率就更高效了
3.叶子节点存储数据记录:每次搜索都必须到达叶子节点才能得到数据,所以当数据量很小的时候走索引还不如直接进行全表扫描
4.自平衡:B+树在插入,删除,或者更新数据的时候,会自动地重新平衡,确保树高度的稳定,从而保持较好的搜索性能。
5.Mysql为什么不用其他的结构
1.B+ 和 B:B+树的叶子节点只存储数据和聚簇索引信息,非叶子节点全部存储的是索引信息以及指针,B树的叶子节点和非叶子节点都存储了索引信息和数据,所以相同IO次数下,B+树查到的数据更多,B+树并且B+树使用了双向链表,这样的方式能够使范围查询和顺序查询更高效。
2.B+树和二叉树:B+树的下一层可以有多个分支,所以其查询的时间复杂度是(logDN)这个D就是这一层的节点数,这就使得即使有1000w条数据,由于D比较大,最多3/4次IO,就能查到了,而二叉树只能有两个子节点,使得得到的树高度太高了
3.B+树和hash :hash的优势在于等值查询的时候效率高,时间复杂度是O(1),但是Hash表不适合做范围查询
6.索引失效有哪些
1.使用模糊匹配的时候,会造成索引失效
2.使用了函数
3.对索引列使用了表达式计算
4.不符合最左匹配原则
5.在where语句中,如果or前面的是索引列,or后面的不是索引列,就会导致索引失效
7.什么是覆盖索引
要查询的内容是一个复合索引,例如我要查询学生表的姓名,年龄,班级,这些字段构成了一个复合索引,就可以直接得到数据。
8.索引的缺点
1.占据一定的物理空间 2.创建索引和维护索引需要一定的时间 3.降低表增删改的效率,每次增删改都会对索引进行一定的调整,需要动态维护
9.索引优化
1.前缀索引优化:将一些字段是长字符串的优化成前缀
2.覆盖索引优化:不用回表了
3.主键索引最好是自增的:这样插入新数据的时候可以直接在上一条数据后面,不需要重新移动数据,而非自增主键在移动数据的时候就会插入到数据中间,甚至引起页分裂(一个一面的数据被移动到了另外一个页面)
五、事务
1.事务的特性
原子性(undo log实现):一个事务中的所有操作要么一起成功,要么一起失败
一致性(其他3个特性保证):事务操作的前后,数据满足完整性约束,数据库保持一致性状态
隔离性(MVCC或锁机制):多个事务同时执行的时候,不会相互影响
持久性(redo log):事务执行结束之后,对数据库的操作是永久的
2.Mysql解决并发问题
锁机制:提供了行级锁,表级锁,页级锁这样的机制,在对数据进行操作的时候上锁可以保证并发问题
事务隔离级别:控制事务隔离的程度,避免数据的不一致性
MVCC:多版本并发控制
3.讲一讲MVCC
MVCC主要是运用于可重复读和读已提交这两种事务隔离级别的情况下,当我们执行一个操作的时候,会有一个日志undo log来记录这个操作的反向操作,如果是添加,那这个操作就是删除,同时数据存储的不仅仅有数据本身还有当前的事务id,和指向上一个数据的指针,一个指向一个就形成了一条版本链,当我们执行一个查询操作的时候,会生成一个read view,里面包含了当前事务id,活跃事务id的集合,活跃事务id集合中的最小id(最小事务id),开启下一个操作的事务id(最大事务id),我们根据当前操作的事务id从版本链最后面进行比对。
如果read view中的数据和当前的事务id一致就返回结果
如果当前的事务id比最小的小,也返回结果
如果当前事务id比最大的大,不返回结果
如果当前事务id在最小和最大的中间,如果不在活跃id集合中就返回结果,在活跃id集合中就不返回结果。
可重复的这样的隔离级别,只会在第一次查询的时候生成一次read view
读已提交这样的隔离级别,每次查询都会生成一次read view
六、锁
1.Mysql中都有哪些锁
全局锁:将数据库变成只读状态,适合用于数据库备份,防止因为其他操作导致的数据不一致
表级锁:表锁:对表进行锁定。元数据锁:针对表结构的锁,分为MDL读锁,和MDL写锁。 意向锁:当执行操作的时候,会对表加上意向独占锁,然后对该记录加独占锁。意向锁的目的是为了快速判断出表里是否有记录被加锁
行级锁:InnoDB支持行级锁,但MyISAM不支持。
记录锁:锁住的是一条记录,而且记录锁是有S锁和X锁之分的,满足读写互斥和写写互斥
间隙锁:只存在于可重复读隔离级别,目的是为了解决可重复读级别下幻读的现象。
临键锁(记录锁+间隙锁):锁定一个范围,并且锁定范围本身
七、日志
1.日志分成哪些部分
redo log(重做日志):存储引擎层的日志:用于实现持久性
undo log(回滚日志):存储引擎层的日志:用于实现原子性,用于事务回滚和MVCC
bin log(二进制日志):Server层的日志,用于数据备份和主从复制
relay log(中继日志):主从复制下,slave通过io线程拷贝master的binlog生成的本地日志
慢查询日志:用于判断哪些查询是属于慢查询,时间较长
2.redo log的作用
1.实现事务的持久性,让Mysql有了灾后重建的能力:进行了一个操作之后并不会立即从buffer pool里面写入到磁盘中,而是先将buffer pool里面的数据写入到redo log这样的日志文件中(WAL),之后再将数据写入到磁盘中
2.将写操作从随机写变成了顺序写,提升了Mysql写入磁盘的性能
3.binlog两阶段提交过程
八、性能调优
1.explain关键字的作用
用于查看sql的执行计划,判断其有没有走索引,每一步消耗的时间
里面存在很多字段,possible_keys,key,key_len,rows等,重点关注type
2.如何优化一条慢sql
1.通过一些配置文件以及慢sql日志查看哪一些sql语句是慢的,耗时了多少秒
2.尽量避免使用select * 这样的语句,将其改为具体的字段,并且联表查询的时候以小表带动大表,尽量使用多个字段在一个表,少用联表查询
3.创建索引
4.通过explain查看是否有走索引,走的索引类型是什么,已便对索引进行优化,避免索引失效等情况
5.分页优化:把limit改成具体的某个位置查询
6.优化数据库表,如果数据量太过于庞大,就取设计分表等
7.使用缓存技术,将热点数据放入到缓存中,不要每次请求都打到数据库上
九、架构
1.Mysql的主从复制
Mysql的主从复制依赖于binlog,复制过程就是将主库的binlog传输到从库(异步进行)
十、总结
本篇文章简单介绍了一下Mysql的一些常见八股,大部分内容都来自于小林coding,链接:MySQL面试题 | 小林coding,感谢观看!