上一篇传送门:点我
JVM是java面试八股中的一个重难点,本文仅是部分问题,SQL语句、主从复制以及数据库锁等知识点还未涉及,后续会进行修改补充。
数据库三大范式是什么?
第一范式:每个字段都不可以再被拆分;
第二范式:在第一范式的基础上,有主键,并且主键之外的其他字段完全依赖于主键,不能是依赖于主键的一部分;
第三范式:在第二范式的基础上,非主键的字段只能依赖于主键,不能依赖于其他的非主键。
什么是索引?说说索引的优缺点
索引是关系数据库中的一种数据结构,它将数据提前按照一定的规则进行排序和组织,能够帮助快速定位到数据记录的数据,从而加快数据库表中数据的查找和访问速度,它的核心思想是以空间换时间。
索引的优点:
1.在大部分场景下,能够提高检索效率;
2.降低排序成本,索引对应的字段是会有一个自动排序功能的,默认是升序。
索引的缺点:
1.创建索引和维护索引需要耗费时间,这种时间随着数据量的增加而增加;
2.索引需要占用物理空间,数据量越大,占用空间就会越大;
3.会降低表的增删改效率,因为每次增删改索引,都需要进行动态维护(因为B+树需要平衡,所以需要自动计算索引的数据结构,这会导致耗时)。
什么时候需要创建索引,什么时候不需要?
适合:
较频繁的作为查询条件的字段应该创建索引,以加快查询的速度和效率
不适合:
1.字段值的唯一性太差(数据太多重复)不适合单独地做索引;
2.更新非常频繁的字段不适合做索引,因为动态维护耗时;
3.不会出现在where语句中的字段不适合做索引(不会作为查询条件,当然也就没有必要作为索引了)。
在mysql中默认的存储引擎和索引的数据结构分别是什么?
mysql中默认的存储引擎是InnoDB,默认的索引数据结构是B+树(在mysql中,当为某一个表创建一个ID主键的时候,mysql就会为一个主键维护一个索引,这个索引的数据结构就是一颗B+树)。
InnoDB和MyISAM的区别
InnoDB和MyISAM是两种不同的数据存储引擎,它们的区别如下:
1.InnoDB支ACID的事务,支持事务的四种隔离级别,而MyISAM不支持事务,每次操作都是原子的;
2.InnoDB支持行级锁及外键约束:因此可以支持写并发,而MyyISAM支持的是表级锁,即每次操作是对整个表加锁;
3.InnoDB不存储表的总行数,而MyISAM会存储表的总行数;
4.InnoDB主键采用的是聚集索引,而MyISAM采用的均是非聚集索引。
说说B树和B+树,它们之间的区别是什么?
B树是一种自平衡的树,能够保持数据有序。在B树中,所有值都出现在叶子节点和内部节点,且内部节点作为索引使用。B树的每个节点通常包含多个子节点,这些子节点的数量受到一定的限制。当进行数据插入或删除时,B树会通过分裂和合并节点来保持平衡。
B+树是B树的一种变种,它也具有平衡和有序的特性。与B树不同的是,B+树的所有值都出现在叶子节点,内部节点仅作为索引使用。此外,B+树的叶子节点通过指针顺序连接在一起,形成一个链表结构,这有利于进行范围查询和顺序访问。
区别:
1.B树的每个索引节点上都会存储对应索引的值,数据和索引节点绑在了一起,而B+树只把数据放在了叶子节点上。
2.B树的叶子节点之间没有连接关系,而B+树的两两叶子节点之间采用了双向链表连接,从而能够使相邻节点快速定位。
3.B树的叶子节点中不会包含内部节点,而B+树的叶子节点中会包含内部节点在内的所有数据。
为什么mysql要选择B+树作为默认的索引数据结构?
1.非叶子节点上能够存储更多键值,相应的树的阶数(节点的子节点树)就会更大,树也就会变得更矮更胖。这样一来执行检索操作进行的磁盘I/O次数就会大大地减少,数据查询的效率也会更快。
2.B+树的叶子节点采用了双向链表,当查询一些范围条件的时候,相比B树查询效率会得到大大提升。
3.由于B+树的所有数据已经通过叶子节点的双向链表排好了顺序,进行排序查询操作时,相比B树性能会快速非常多。
什么是聚集(聚簇)索引和非聚集索引?谈谈它们的区别
此处参考:https://www.cnblogs.com/xiaomaomao/p/16196006.html
聚集索引是指数据库表行中数据的物理顺序与键值的索引顺序相同,对于聚集索引,数据库数据和索引将设计到一个文件中,叶子节点包含了所有数据记录。
Innodb的主键索引就是通过聚集索引实现的。
例如数据库中有一张 id 为主键的user 表如下:
那么基于这张表的主键 id 建立的聚集索引如下图所示,可以看出,叶子节点包含了完整的表数据。
因为表中存储的数据是通过聚集索引组织在一起的,所以聚集索引必须要有,否则我们无法获取到表中的行数据,并且聚集索引还只能存在一个。
由于聚集索引必须存在,所以对于聚集索引有以下规则:
- 如果存在主键,那么主键索引就是聚集索引
- 如果不存在主键,将会使用第一个唯一(UNIQUE)、非空的索引作为聚集索引
- 如果表中既没有主键索引,又没有合适的唯一索引,那么 Innodb 会自动维护一个 row_id(默认大小为 6B)来作为隐藏的聚集索引
非聚集索引是指数据库表行中数据的物理顺序与键值的索引排列顺序无关,它把索引和行数据分开维护,叶子节点并没有包含完整的数据记录。(个人理解:当主键存在时,可以把它看作非主键索引)
Innodb 以 age 建立的非聚集索引如下图:
重点:当通过非聚集索引来查询数据时,存储引擎会根据索引字段定位到最底层的叶子节点,并通过叶子节点获得指向主键索引的主键 id,然后通过主键 id 去主键索引(聚集索引)上找到一个完整的行记录.这个过程被称为回表。
聚集索引与非聚集索引的区别有以下几点:
1.一个表中只能拥有一个聚集索引,而非聚集索引一个表可以存在多个。
2.聚集索引,索引中键值的逻辑顺序决定了表中相应行的物理顺序;非聚集索引,索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。
3.索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
4.聚集索引:物理存储按照索引排序;非聚集索引:物理存储不按照索引排序;
什么是联合索引?
联合索引就是好几个字段组成的索引。它遵循“最左匹配原则”,没有最左边的索引值,就没办法使用这个索引。在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,顺序不对时引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。可以说创建的idx_abc(a,b,c)索引,相当于创建了(a)、(a,b)(a,b,c)三个索引。由于构建一棵B+树只能根据一个值来确定索引关系,所以数据库依赖联合索引最左的字段来构建。
什么是最左前缀原则?
最左前缀原则(也称最左匹配原则)指的是在查询过程中,索引的利用是从联合索引的最左边开始,并逐列进行匹配。在创建联合索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
例如,创建一个组合索引(a1,a2,a3),相当于创建了(a1)、(a1,a2)和(a1,a2,a3)三个索引,这就是最左匹配原则。
什么是覆盖索引?
需要注意,覆盖索引是一种数据查询方式,不是索引类型。覆盖索引也叫索引覆盖,它是一种查询优化技术,在某些情况下可以避免执行回表操作,以提高查询性能。
当使用非聚集索引查询时,如果查询语句中只使用了索引列,而没有查询表中的其他列,那么可以使用索引覆盖来避免回表操作。在这种情况下,查询可以直接从索引中获取所需的数据,而不需要再回到表中查找数据。这可以减少IO操作,提高查询性能。
数据库事务是什么?
数据库事务是访问并可能操作各种数据项的一个数据库操作序列,它是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么全部执行,要么全部不执行,是一个不可分割的工作单位。一个事务由该事务开始与该事务结束之间所执行的全部数据库操作组成。
谈谈数据库事务的基本特性
数据库事务的基本特性为 “ACID”。
1.原子性(atomicity): 事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做。
2.一致性(consistency): 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
3.隔离性(Isolation): 一个事务的执行不能其它事务干扰。即一个事务的修改在最终提交前,对其他事务是不可见的。
4.持久性(Durability): 一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
什么是MVCC?
MVCC的中文是多版本并发控制器,是为了在读取数据时不加锁的情况下实现读写不冲突来提高读取效率和并发性的一种手段。它的基本思想是:为每个数据记录维护多个版本,允许并发事务在不相互阻塞的情况下读取不同版本的数据。
MVCC会为每个修改保存⼀个版本,版本与事务的时间戳关联,当事务开始时,会记录当前的最新版本号。在事务执行过程中,只能读取到版本号小于等于事务开始时的版本。读操作只读该事务开始前的数据库版本的快照。当进行写操作时,会生成新的版本并更新到数据行中。旧的版本仍然存在,不会被删除。这样可以使得其他正在进行的事务可以继续读取到旧的版本,不会被阻塞。
数据库事务的四大特性都是如何保证的?
原子性是通过undo log日志和回滚来保证的,在开启事务时,会将事务开始时的原始数据保存在undo log中,如果事务失败,将通过回滚撤销该事务已做的所有修改,并通过undo log将数据库恢复到事务开始前的状态;
一致性是通过强制执行完整性约束(如主键约束、外键约束等)和使用触发器等技术来保证;
隔离性是由MVCC来保证的,由于不同的事务在版本控制下会属于不同的版本,因此可以实现不同事务的相互隔离;
持久性由内存和redo log来保证,事务提交的同时,mysql会在内存和redo log中记录这次修改操作,系统发生故障的时候可以从redo log恢复已提交的修改。
数据库事务的隔离级别
首先,先来介绍一下数据库事务的常见并发问题,数据库事务的并发问题主要有以下几种:
1.脏读: 一个事务读取到另一个事务未提交的数据。
2.不可重复读: 一个事务对同一行数据重复读取两次,但得到的结果不同。
3.幻读: 一个事务执行两次查询,但第二次查询的结果包含了第一次查询中未出现的数据。
4.丢失更新: 两个事务同时更新一行数据,后提交(或撤销)的事务将之前事务提交的数据覆盖了。
数据库事务的隔离级别有4个,由低到高依次为读未提交、读已提交、可重复读、可串行化四个级别,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
读未提交: 一个事务在执行过程中,既可以访问其他事务未提交的新插入的数据,又可以访问未提交的修改数据。如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据。此隔离级别可防止丢失更新,但是会出现脏读,不可重复读,幻读问题。
读已提交: 一个事务在执行过程中,既可以访问其他事务成功提交的新插入的数据,又可以访问成功修改的数据。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行数据。此隔离级别可有效防止脏读问题,但是会出现不可重复读,幻读问题。
可重复读取: 这是mysql事务的默认隔离级别。一个事务在执行过程中,可以访问其他事务成功提交的新插入的数据,但不可以访问成功修改的数据。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。此隔离级别可有效防止不可重复读和脏读问题,但是会出现幻读问题。
可串行化: 提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。此隔离级别可有效防止脏读、不可重复读和幻读。但这个级别可能导致大量的超时现象和锁竞争,在实际应用中很少使用。
Mysql慢查询该如何优化?
- 检查查询是否走了索引,如果没有则优化SQL利用索引;
- 检查所利用的索引,是否是最优索引;
- 检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据;
- 检查表中数据是否过多,是否应该进行分库分表;
- 检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源。