数据库面试题01:基础知识


1. 事务四大特性?

原子性(Atomicity)

  • 事务包含的所有操作要么全部成功,要么全部失败回滚。

一致性(Consistency)

  • 事务开始前和结束后,数据库的完整性约束没有被破坏。包括一致读和一致写
  • 假定有一个事务序列,T1,T2… Tn,数据库的状态是执行T1前为C0,执行后为C1,执行T1后是C1,依次类推,执行Tn后是Cn。
    • 一致读:任何事务都只能读取到Ti运行后的完整状态Ci,而不可能读取到一部分Ci一部分Ci-1的状态。
    • 一致写:一个状态只能由一个事务导致,不能由两个事务同时导致。

隔离性(Isolation)

  • 多个用户并发访问数据库时,数据库为每一个用户开启的事务,且不被其他事务的操作所干扰。同一时间,只允许一个事务请求同一数据。

持久性(Durability)

  • 事务一旦被提交,数据的改变就是永久性的。
  • 服务器硬盘发生故障时怎么办?根据RAID Level 进行对应的校验恢复。

2. 事务的并发?事务隔离级别?每个级别会引发什么问题?MySQL、Oracle默认是哪个级别?

2.1 事务的并发

(1)脏读:T1没有COMMIT以前,就让T2读到了T1尚未COMMIT的数据。

(2)不可重复读:T1已经COMMIT了一个数据记录的修改,T2在T1 COMMIT同一条数据以前访问过这个数据,在T1 COMMIT后发现数据被修改了。

(3)幻读:T1添加了一条数据并且COMMIT,T2在开始时没有发现这条数据,但是后来发现了。

2.2 事务的隔离级别

(1)READ UNCOMMITTED: 读未提交 =》 可能的问题:脏读,不可重复读,幻读

(2)READ COMMITTED:读已提交 =》 可能的问题:不可重复读,幻读

(3)REPEATABLE READ:可重复读 =》 可能的问题:幻读

(4)SERIALIZABLE:串行化 =》 没有问题

2.3 事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持。

​ MySQL默认的事务隔离级别为REPEATABLE READ,MySQL支持 4 中事务隔离级别。

​ Oracle默认的事务隔离级别为READ COMMITTED,Oracle 支持的 2 种事务隔离级别 READ-COMMITED , SERIALIZABLE

2.4 补充

  1. MySQL中默认事务隔离级别是“可重复读”时并不会锁住读取到的行
  • 事务隔离级别未提交读时,写数据只会锁住相应的行。
  • 事务隔离级别为可重复读时,写数据会锁住整张表。
  • 事务隔离级别为串行化时,读写数据都会锁住整张表。

3. 查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?

SELECT DISTINCT
    列名
FROM
    表名1
    JOIN 表名2 ON 条件J
    ...
WHERE
    条件1
GROUP BY
    列名
HAVING
    条件2
ORDER BY
    列名
LIMIT 分页限定

第1步,得到所有表的记录
第2步,根据WHERE中的条件1中的单表条件来过滤记录
第3步,对多表的记录进行笛卡尔积,获得笛卡尔积记录,同时使用条件J和条件1中的跨表条件来过滤笛卡尔积记录
第4步,补齐外连接
4.1,左外连接,把左表没有参与过笛卡尔积运算的记录全部补全,右表补NULL
4.2,右外链接,把右表没有参与过笛卡尔积运算的记录全部补全,左表补NULL
第5步,根据列名分组
第6步,在分组内部,利用聚合函数对非分组列进行计算
第7步,把需要新加的列加上
第8步,把不需要的列去掉
第9步,根据HAVING中的条件对结果进行过滤
第10步,去重
第11步,排序
第12步,分页

顺序:WHERE中的单表条件 => JOIN和WHERE中的跨表条件 => GROUP BY => HAVING的条件 => limit

4. 什么是临时表,临时表什么时候删除?

MySQL 临时表在我们需要保存一些临时数据时是非常有用的。

临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间;当然,也可以手动删除临时表。

例如:

CREATE TEMPORARY TABLE tmp_table (
       NAME VARCHAR (10) NOT NULL,
       time date NOT NULL
);
select * from tmp_table;

需要手动删除时:

DROP TEMPORARY TABLE IF EXISTS temp_tb;

5. 关系型数据库的 B+Tree索引和Hash索引的区别?

  • Hash索引结构:是通过Key和哈希函数,计算哈希值并把哈希值最为存储的数组下标。

  • B+树索引结构:是M叉平衡查找树,以及串起所有叶子节点的链表

    Hash索引相比于B+Tree索引的缺点:

(1)查询方面:Hash索引仅仅能满足”=”,”IN”和”<=>”查询,不能使用范围查询,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样;

(2)排序方面:Hash索引无法被用来避免数据的排序操作,因为Hash值的大小关系并不一定和Hash运算前的键值完全一样;

(3)索引方面:Hash索引不能利用部分索引键查询,对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用;

(4)Hash自身方面:Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要回表查询数据;

(5)性能方面:Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高。

某些关系型数据库是可以使用Hash索引的

MySQL中,HEAP/MEMORY引擎可以显示支持Hash索引,而常用的InnoDB引擎中默认使用的是B+树索引

只有在查询是Key-Value这种情况,没有范围查询,没有模糊查询,没有排序,且键值重复性小时,才推荐Hash索引。

6. 简述索引如何加速查询?

  1. 索引是指定新的列,为该列建立B+Tree结构

  2. 有索引时,操作<,<=,=,>,>=,between,in,以及不使用通配符开头的like,会被加速。

  3. 添加索引后,对应列的查找时间从O(N)下降到O(LogN)

7. 聚集索引和非聚集索引区别?

索引(在MySQL中也叫做“键(key)”) 是存储引擎用于快速找到记录的一种数据结构。这是索引的基本功能。

聚集索引 clustered Index

聚集索引

非聚集索引 unclustered Index

image-20220710165659145

不同点: 聚集索引的叶子节点存放是一整行的信息。 聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。 聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续(通过指针调用来实现连续),物理存储并不连续。 聚集索引查询数据速度快,插入数据速度慢;非聚集索引反之。 聚集索引范围查询快。

  1. 每张表有且只有一个聚集索引,如果在建表的时候定义了主键,主键就是聚集索引,如果没定义有一个缺省的。(有一种说法是聚集索引的索引排列顺序和表记录的排列顺序一致,是的,所谓表记录的排列顺序就是B+Tree结构中链表的顺序)
  2. 非聚集索引可以有多个。(非聚集索引是另外增加的B+Tree结构,最后通过指针指向单条数据记录)
  3. 增加索引可以提高SELECT速度。
  4. 增加索引会减慢INSERT,DELETE的速度。

具体的引擎,实现聚簇索引的区别也有所不同,详情可看这个大佬的一篇博客:MySQL索引背后的数据结构及算法原理

8. 关系型数据库和非关系型数据库的区别(SQL与NoSQL的区别)?

非关系型数据库的优点:

  1. 性能:比如Redis,底层使用跳表,在并发方面表现更加优异
  2. 可扩展:无论是跳表还是Hash表,耦合性都很低,分布式存储不像B+Tree那样复杂。

关系型数据库的优点:

  1. 支持复杂的SQL查询
  2. 支持事务

9. 简述什么是数据库的三范式?

第一范式:每一个列都是不可分割的原始数据项。第一范式解决的是如何把数据放到一张二维表里。(最基本要求

第二范式:在第一范式的基础上,不存在部分函数依赖,即所有的非主属性都完全的依赖主属性。第二范式解决的问题:部分的,数据冗余,删除错误,插入困难

​ 函数依赖:A -> B,对两列中的任意记录,通过属性A的值可以确定属性B的值,我们说B依赖于A;A也可以是一组属性,同理

​ 完全函数依赖:A -> B,A是一组属性,如果B依赖于A,且B不依赖于任何A的子集,我们说B完全依赖于A。

​ 部分函数依赖:A -> B,A是一组属性,如果B依赖于A,且存在B依赖于A的某个子集,我们说B部分依赖于A。

第三范式:在第二范式的基础上,非主属性不存在传递依赖。第三范式解决的问题:数据冗余,删除错误,插入困难

​ 传递函数依赖,A -> B, B -> C,即C完全依赖于B,B完全依赖于A,我们说C传递依赖于A。

BC范式:在第二范式的基础上,所有的属性都不存在传递依赖

10. 什么是 内连接、外连接、交叉连接、笛卡尔积等?

SQL中两张表,左表和右表

内连接,只有同时满足连接条件的左表记录和右表记录才能连接成为新的记录。

外链接,分为左外链接和右外连接

​ 左连接,左表中的全部记录和右表中满足连接条件的记录能够根据条件连接成为新的记录,如果某些左表中记录找不到符合条件的右表记录,则对应列写NULL。

​ 右连接,左表中满足连接条件的记录和右表中的全部记录能够根据条件连接成为新的记录,如果某些右表中记录找不到符合条件的左表记录,则对应列写NULL。

交叉连接:没有连接条件,左表和右表中的记录排列组合连接成为新的记录,这种连接的结果也成为笛卡尔积。也就是说内连接是在交叉连接的基础上根据连接条件对笛卡尔积的结果进行了过滤。

11. varchar和char的区别?

char:

​ char类型是固定长度类型,例如char(20)是一个长度为20字节的空间。如果放入的字符串长度不足20字节,尾部会用空格填满,然后在查询时会自动删除后边结尾的空格。所以char类型是不能存储结尾有空格的字符串的

varchar:

​ varchar类型是可变长度类型,例如varchar(20)是指最长可以放20个**字符**的空间,而不考虑字符的字符集,以及具体字符占用的字节数。事实上,varchar类型在最后还保存了一个字符串字符长度的值。


文章作者: 银色回廊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 银色回廊 !
评论
  目录