【工业化面试】之mysql

前言

数据库相关知识对于一个程序员来说是基本的知识储备,本文从面试官的角度来写,通过问答的方式来对数据库知识进行一次扫盲。就数据库的知识点,模拟一个考察数据库知识的面试场景,并尽可能地使提问具有逻辑性。


正文

1、我看到你简历上提到了对Mysql是比较熟悉的对吧,那一般情况下mysql该怎么去优化它的查询呢?

答:嗯~首先就是建立索引,可以使用explain命令看看是否使用了索引,如果没有的话就建立索引;然后就是尽量避免全表扫描,所以要在where和order by这样的操作的相关列建立索引;然后就是避免使用“select * ”,因为这样的语句查询的数据量会很大,相应的磁盘IO量就大了;然后就是避免频繁创建和删除临时表,因为这样会造成表资源的浪费。

2、好的,那mysql索引有几种方式?有几种类型?

答:常用的索引方式有Hash、B树、B+树等等,然后索引类型有聚集索引、非聚集索引、唯一索引、普通索引、主键索引、全文索引。

3、嗯,那为什么用B+树,而不用平衡二叉树、红黑树之类的索引呢?

答:这主要是因为二叉树高度太高,我们知道,查询的时间主要是由磁盘访问时间和CPU计算时间组成的,而CPU计算时间很短,所以磁盘访问次数就成为了性能瓶颈,查找树每多一层,需要访问磁盘的次数就多一次,在相同关键字的情况下,B+树的高度要比二叉树小得多,所以使用B+树。

4、那树低的也有B树啊,为什么它用B+树呢?

答:嗯~B+树其实是对B树的一个优化,因为它的结构就是中间节点不存数据,数据都存在叶子节点上,这样就使得中间节点能够存储更多的key;其次就是B+树的叶子节点使用链表相连,更便于范围查找和遍历,而B树的范围查询需要进行层序遍历,节点相邻的元素在内存中不一定相邻,所以缓存命中率没有B+树高。

5、那你知道MyISAM和InnoDB的区别吗?

答:MyISAM不支持事务,而InnoDB支持事务;MyISAM支持表级锁,InnoDB支持行级锁;MyISam支持全文索引,而InnoDB不支持全文索引;MyISAM支持管理非事务表,提高了全文检索的能力,如果业务上需要大量的select操作,可以考虑使用MyISAM,而InnoDB支持事务操作,比较适合大量update和insert操作。

6、好的,我们回到上面的问题,你能说说聚集索引和非聚集索引的区别以及分别说说它们的使用场景吗?

答:嗯~聚集索引的数据行的物理顺序和索引顺序是一致的,且聚集索引的物理存储是连续的,一张表只能存在一个聚集索引;非聚集只具有逻辑上的相关性,就是说物理上并不连续,然后一张表可以有多个非聚集索引。

使用场景的话,聚集索引适用于查询频繁而更新不频繁的列,因为如果频繁对列进修改,为了维持物理顺序的一致性,需要移动对应数据的物理地址;聚集索引适合包含大量重复值的列;然后聚集索引适合范围查询,因为聚集索引的数据具有物理上的连续性。非聚集索引适合频繁更新的列;非聚集索引适合返回精确查询的列,所以它也适合包含大量非重复值的列。

7、嗯,我看到你项目里使用了redis啊,那么多缓存中间件比如Memcache,为什么会选择redis呢?

答:这个一方面是因为redis支持的数据格式要比memcache多,memcache只支持简单的数据类型,而redis支持list、set、zset、hash等数据结构;另一方面是因为redis的数据持久化机制,将数据持久化到磁盘中,故障重启时可以恢复,而memcache数据没有持久化机制,一旦机器宕机,所有的数据都会丢失。

8、嗯,你刚刚说了redis的持久化机制,那我假设机器断电了,redis要怎么把数据恢复呢?

答:好的,我先说说redis的持久化机制吧,redis持久化机制有2种,分别是RDB和AOF。RDB是每隔一段时间将数据的快照持久化到数据库中。RDB是全量备份的,比较耗时,而且备份期间redis产生的修改无法持久化到磁盘中,所以出现了AOF持久化机制,AOF的工作机制很简单,就是将redis收到的写命令都通过一个write函数追加到一个文件中,通俗来说,就是将操作写入到一个日志(AOF)文件中。

假设机器断电了,我们可以使用RDB进行灾难恢复,但是RDB存在数据丢失的风险,因为没有进行持久化的数据无法恢复,AOF恢复的数据全,但是恢复的速度比较慢,所以我们通常让两种持久化方式一起工作来共同实现灾难恢复,就是通过RDB来实现一个快速数据恢复,然后使用AOF来进行丢失数据的恢复。

9、你了解过redis集群吗?

答:了解过的,redis集群分为三种模式,分别是主从模式、sentinel模式和cluster模式。主从模式就是一主多从的集群,master节点提供读写服务,slave节点只能通过读服务,并接受从master节点同步过来的数据,当master宕机了之后,slave可以继续提供读服务,但是由于主从模式不会从从节点中选出一个新的master,所以此时集群只能提供读服务,而不能提供写服务。从节点宕机了之后不会影响集群的读写服务,从节点重启之后会从master中同步数据。

由于主从模式不具备高可用性,当master宕机之后不能再对外提供写服务,所以产生了sentinel模式,sentinel意为哨兵,就是用来监控集群节点的进程,当master节点宕机之后,sentinel会从slave节点中挑一台机器作为master,同时修改所有节点的配置信息,当master节点重启之后,会作为一个slave节点去向master同步数据。同时sentinel因为是一个进程,也有可能挂掉,所以通常使用一个sentinel集群来监控redis,sentinel进程之间也可以互相监控,一个sentinel集群可以监控多个redis主从集群,多个sentinel集群也可以监控一个redis集群。通常redis和sentinel不应放在同一个节点中,不然redis挂了,sentinel也挂了。

一般来说,sentinel模式已经足够满足日常生产需求了,但是当数据量大到一台机器放不下时,就需要cluster模式,cluster模式下,数据会按一定规则分配到多个节点上,所有节点都是主从模式,但是slaver不提供服务,仅作备用。客户端可以连接任何一个主节点进行访问。

10、嗯,那你说一下主从模式下集群是如何保证数据的一致性的。

答:嗯~首先slaver启动之后,会向master发送预估SYNC命令,master接收到SYNC命令后,进行RDB持久化,并将持久化过程中的执行命令缓存起来,持久化完成之后,将持久化文件和缓存命令一起发送给slaver,slaver接收到RDB文件和缓存后,开始加载快照文件,并执行缓存中的命令,这样就实现了数据一致性。初始化之后,master以后每次接收到写命令,都会同步发送给slaver,保证数据的一致性。

11、嗯,说说缓存穿透和缓存击穿的区别吧。

答:缓存穿透是由于查询的数据既不在redis中,也不在数据库中,比如查询id为-1的记录,如果大量这样的请求冲击数据库,就可能导致数据库崩溃,通常这样的情况可能是恶意攻击导致的;缓存击穿是由于热点数据缓存过期,导致大量请求直接冲击数据库而导致数据库崩溃。

我顺便说说它们的解决办法吧,处理缓存穿透呢,可以在redis中缓存null值,如果之后再访问这个数据,就直接从缓存中获取,这样就保护了数据库;或者使用布隆过滤器,将所有可能查询的参数以hash的形式存储,当用户查询的时候,如果查询的值不在集合中,就直接丢弃,不再对持久层进行访问。处理缓存击穿的话,可以设置热点数据的缓存永久不过期,或者提前预估热点数据的到期时间,进行重新设置,防止热点数据缓存过期。


结尾

如果能答到这里,说明对数据库的知识已经有了一定的储备,这些问题只是很小的一部分,但是作为应届生来说,应该够撑10分钟了(笑哭),面试官应该也不会一直和你死磕数据库。所以,关于数据库的知识就先到这里吧。以后有时间再补一补。
秋招加油!!!

猜你喜欢

转载自blog.csdn.net/qq_37163925/article/details/106150107