文章目录
- 一、数据库基本概念
- 1. 超键、候选键、主键、外键是什么?
- 2. 什么是存储过程?有哪些优缺点?
- 3. 什么是触发器?有什么作用?
- 4. 什么是视图?有什么作用?
- 5. 三个范式是什么?
- 6.什么是事务?事务有哪些隔离级别?
- 7. 谈一谈乐观锁和悲观锁?
- 8. 关系型数据库和非关系型数据库各有什么优势?
- 9. 谈谈MySQL常见的存储引擎?
- 10. InnoDB为什么推荐使用自增主键?
- 二、SQL语句
- 1. 说说drop、truncate、 delete区别和应用场景?
- 2. 说说char和varchar的区别?
- 3. SQL约束有哪几种?
- 三、索引
- 1. 索引是什么?优缺点是什么?
- 2. 索引的应用范围(什么情况下使用索引)?
- 3. 索引有哪些分类?聚合索引和非聚合索引的区别?
- 4. 索引为什么使用B+树而不是Hash索引?
- 5. B树和B+树有什么区别?它们两个哪个更适合做索引?
- 四、参考资料
一、数据库基本概念
1. 超键、候选键、主键、外键是什么?
超键:能唯一标识某条数据的属性集合,比如身份证号、学号等等。
候选键:最小的超键。比如学号或身份证号。
主键:人为规定的候选键,能够标识出某一条数据。
外键:另外一个表的主键在这个表中的引用称为外键,用来描述两个表的关系。
2. 什么是存储过程?有哪些优缺点?
存储过程是一组预编译的SQL语句,封装了多个SQL,就像编程语言中的函数一样,创建一次,就能被多次调用。
优点:
- 存储过程是预编译过的,执行效率比单独执行每一条语句要高。
- 存储过程的代码存在数据库中,通过存储过程名直接调用,可以减少网络通信量。
- 存储过程可以重复使用,有效减少开发人员的工作量。
缺点:
- 将核心逻辑放在数据库中,难以更新、迭代。
- 移植性差,不同数据库的存储过程实现几乎不同。
3. 什么是触发器?有什么作用?
触发器是一种特殊的存储过程,通过事件的触发来执行,比如修改、插入、删除特定表中的数据时执行。可以用来强化约束,维护数据的完整性和一致性。比如说删除某个班级后,将属于该班级学生的班级置为空。
4. 什么是视图?有什么作用?
视图是一种虚拟的表,建立在现有表的基础上,通常为一个或多个表的子集。
有时候,我们不希望表中的所有字段被看到,就可以将表中的部分字段封装为一个视图,以供他人查询。而且,对于一些复杂的连结查询,使用视图能让开发者注重逻辑,简化编码流程。
5. 三个范式是什么?
第一范式:字段是最小的单位,不可再分。例如姓名字段,不能拆分成姓和名。
第二范式:表中的字段必须完全依赖于主键。例如我的姓名是xxx,我的年龄是21,这都依赖于主键学号。
第三范式:表中的字段都与主键直接相关,而不能间接相关。例如订单表中关联用户信息,那么就只用关联id就行,不用把用户的姓名、年龄等等信息都加入。这样能消除传递依赖,就是当用户信息更改后,还需要更改订单表中的一堆字段。
6.什么是事务?事务有哪些隔离级别?
事务指的是一个操作序列,要么同时成功,要么同时失败,它是一个不可分割的工作单位。
事务有四个特性:
- 原子性:事务中的所有操作像原子一样不可分割。
- 一致性:事务执行后,必须从一个一致性状态转为另一个一致性状态。
- 隔离性:并发执行的事务不会相互影响。
- 持久性:事务一旦提交,对数据库的更改是持久的。
事务的隔离级别,就和以下几种并发异常相关:
- 脏读:事务A修改了数据,未提交。事务B读到了这个未提交的数据,然后事务A回滚了数据,这样,事务B就读到了错误的数据。
- 不可重复读:事务A读一个数据,然后事务B修改了这个数据并提交,然后事务A又读取这个数据,导致两次数据不一样。
- 幻读:事务A查找年龄小于20的学生,事务B添加了一个年龄为19的学生并提交,然后事务A又查找年龄小于20的学生,导致两次结果不同。
幻读和不可重复读的区别在于,前者是不确定的多行数据,后者是针对一行数据。
事务的隔离级别,从低到高分别为:
隔离级别 |
概述 |
脏读 |
不可重复读 |
幻读 |
读未提交(READ UNCOMMITTED) |
直接读取任何数据 |
√ |
√ |
√ |
读已提交(READ COMMITTED) |
只能读取已提交的数据 |
|
√ |
√ |
可重复读(REPEATABLE READ) |
读取数据时不允许其他事务修改,但可以写入 |
|
|
√ |
串行化(SERIALIZABLE) |
串行读取,效率低 |
|
|
|
事务的隔离级别越低,并发异常越容易出现,但并发性也越强。
7. 谈一谈乐观锁和悲观锁?
乐观锁和悲观锁都是数据并发的控制手段。
悲观锁认为要修改的数据很可能已经被其他事务修改过了,那么就提前获取锁,然后再查找,再修改。在MySQL中使用select for update
来实现悲观锁。
乐观锁认为要修改的数据应该没有被其他事务修改过,所以先查,再判断这个数据是否被动过,如果没动过,那就直接修改,如果动过,那就回滚。一般的做法是加个时间戳或版本号。
使用场景:
- 速度需求方面:如果需要响应速度很快,那么使用乐观锁会更好,不需要提前等待锁,并发性会更高。
- 冲突频率方面:如果冲突频率很高,那么使用悲观锁更好,减少了不必要的回滚操作。
- 回滚代价方面:如果回滚代价很高,那么使用悲观锁更好。因为使用乐观锁一旦发现数据被改过,就得回滚事务,代价就很高。
8. 关系型数据库和非关系型数据库各有什么优势?
关系型数据库的优势是:能在多个表之间做非常复杂的查询操作,而且支持事务。
非关系型数据库的优势是:基于键值对存储,存取效率高。而且数据之间没有耦合性,易横向拓展。
对于这两种类型的数据库,对方的优势就是自己的弱势。
9. 谈谈MySQL常见的存储引擎?
常见的存储引擎有InnoDB、MyISAM。它们的主要区别是:
- 事务方面:InnoDB支持事务,MyISAM不支持事务。
- 外键方面:InnoDB支持外键,MyISAM不支持外键。
- 全文搜索方面:InnoDB不支持,MyISAM支持。
- 锁的粒度方面:InnoDB支持行锁,MyISAM支持表锁。
- 索引方面:InnoDB是聚集索引,MyISAM是非聚集索引。
MySQL 5.5.5之后,InnoDB是默认引擎。
如果应用程序要使用事务,或者需要频繁修改数据,那么就要用InnoDB引擎。如果主要以查询为主,那就使用MyISAM引擎。
10. InnoDB为什么推荐使用自增主键?
自增主键可以保证每次插入时B+树的索引都是从右边拓展,可以避免树的频繁合并和分裂。如果使用随机字符串(如UUID)做主键,会使得插入的效率会变低。
二、SQL语句
1. 说说drop、truncate、 delete区别和应用场景?
作用:
区别:
- 回滚方面:drop和truncate是立即生效,不支持回滚。delete事务提交才会生效,支持回滚。
- 速度方面:delete是删除部分行,会被记录在rollback segment中,而且可能激活触发器,速度慢一些。truncate不会加入rollback segment,也不会激活触发器,速度更快。
- 应用范围方面:truncate只能用于表,delete可以用于表和视图
应用场景:
- 不再需要一张表的时候,用delete;
- 需要清空表中的数据时,用truncate;
- 需要删除表中的部分数据时,用delete;
2. 说说char和varchar的区别?
- 长度方面:char的长度是不可变的,varchar长度是可变的。例如定义一个char(10)和一个varchar(10),如果在里面放入’hello’这个字符串,char占的长度还是10(前面5个是hello,后面5个是空格),而varchar的长度是5。取数据时,char类型的需要trim()去掉右边的空格,而varchar不需要。
- 效率方面:char类型因为固定了长度,方便查找和存储,读写速度要比varchar快。就是说char用空间换了时间效率。
- 存储方式方面:char存储英文字符占1字节,汉字占2字节。varchar存储英文字符和汉字都是2字节。
3. SQL约束有哪几种?
约束名 |
作用 |
NOT NULL |
非空约束,该字段的内容一定不为空 |
UNIQUE |
独特约束,该字段的内容不能重复 |
PRIMARY KEY |
主键约束,该字段的内容不能重复,一个表只能出现一个 |
FOREIGN KEY |
外键约束,该字段是其他表主键的引用 |
CHECK |
范围约束,控制该字段的取值范围 |
三、索引
1. 索引是什么?优缺点是什么?
索引它本身就是一个数据结构(通常为B树和B+树),就像新华字典的目录一样。
优点:能大幅提升查找的效率。
缺点:当对表中数据进行增加,修改,删除时,还会涉及到索引的维护,导致效率变慢。而且索引需要占物理空间。
2. 索引的应用范围(什么情况下使用索引)?
索引是建立在数据表的某些列上面,有些列适合创建索引,有些列不适合创建索引。
一般来说,应该在这些列上创建索引:
- 经常需要搜索的列(包括范围搜索),可以加快搜索速度;
- 作为主键的列,强制列的唯一性;
- 提供连接的列,如外键,能加快连接速度;
- 经常出现在WHERE字句中的列,能加快判断速度;
有些情况,不应该创建索引:
- 表很小,没有多少记录;
- 表频繁进行添加、修改、删除操作;
3. 索引有哪些分类?聚合索引和非聚合索引的区别?
- 唯一索引:不允许两行具有相同的索引值。
- 主键索引:是唯一索引的特殊情况,不允许相同,而且不允许为空。
- 聚集索引:索引顺序和表记录的顺序一致。
- 非聚集索引:索引顺序和表记录的顺序不一致。
聚集索引,内部结构为B+树,叶子节点中包含了指向相邻节点的指针。因为其索引顺序和表记录的顺序一致,所以查询效率会很高。因为找到一个索引值的记录后,其连续的记录也存放在一起。但是修改过程比较慢,因为要保证有序性并维护树的结构,可能在数据插入、删除时内部的B+树会分裂和重组。
非聚集索引,内部结构也是B+树,但它叶子节点中不是保存的数据,而是指向对于数据的指针。所以索引顺序和实际表记录中的顺序不一致。
它们的根本区别就是在索引的排列顺序和表记录的排列顺序是否一致。
4. 索引为什么使用B+树而不是Hash索引?
- 由于Hash表的独特结构,使得在查找一个确定值的时间复杂度到达O(1),适合
=
,IN
这种类型的查询。但它不适合范围查询,一是效率慢,而是查到的顺序也不同。而大多数查询情况下,都有范围查询,按序等特征,所以使用B+树更好。
- Hash索引在有大量Hash冲突时,就是大量Hash值相等的情况,效率甚至不如B+树。
5. B树和B+树有什么区别?它们两个哪个更适合做索引?
B树是所有节点都储存键值对,B+树是所有的叶子节点储存键值对,树枝节点作为索引部分。
B+树更适合做索引,原因如下:
- B+树的磁盘读写代价更低。因为B+树的有效数据全在叶子节点上,相对于B树来说,更矮更胖。然后索引都是以文件形式存储的,树越矮,磁盘IO的次数就越少。
- B+树查询效率更加稳定。因为有效数据全在叶子节点中,所以每次都是从根节点走到叶子节点。
- B+树方便范围查询。B+树的叶子节点可以添加指向相邻叶子节点的指针,叶子节点之间形成有序链表。
四、参考资料
-
史上最全的数据库面试题,不看绝对后悔
-
数据库面试题目汇总
-
数据库面试题(开发者必看)