数据库面试题(基础常考!!!)
在数据库领域,无论是日常开发还是面试场景,都有一些高频且重要的问题需要我们深入理解和掌握。本文将对这些常见面试题进行详细阐述,帮助大家更好地应对面试和实际工作中的挑战。
面试题一:三范式详解
什么是三范式
三范式是关系型数据库中用于规范数据结构的重要准则,包含第一范式、第二范式和第三范式。
假设存在一个学生成绩表,字段有:学号、姓名、课程名称、成绩、课程学分。数据如下:
学号 | 姓名 | 课程名称 | 成绩 | 课程学分 |
---|---|---|---|---|
001 | 张三 | 数学 | 90 | 4 |
001 | 张三 | 英语 | 85 | 3 |
002 | 李四 | 数学 | 88 | 4 |
002 | 李四 | 英语 | 82 | 3 |
- 第一范式(1NF):要求每一列都是不可再分割的最小单元。在此例中,所有字段(学号、姓名、课程名称、成绩、课程学分)都已达到最小数据单元,不可分割,符合第一范式。
- 第二范式(2NF):在满足第一范式的基础上,非主属性必须完全依赖于主属性。若将(学号,课程名称)设为主键,其他字段(姓名、成绩、课程学分)都完全依赖于这个主键,满足第二范式。
- 第三范式(3NF):在满足第二范式的基础上,非主键字段不能依赖于其他非主键字段。此例中,姓名依赖于学号,成绩和课程学分依赖于(学号,课程名称),不存在非主键字段相互依赖,满足第三范式。
简单概括,第一范式是确保列的原子性;第二范式是在原子性基础上,保证非主键对主键的完全依赖;第三范式是在前两者基础上,杜绝非主键之间的相互依赖。
为什么要遵循三范式
遵循三范式主要有两个目的:一是减少数据冗余,避免数据的重复存储,节省存储空间;二是方便数据的维护和更新,确保数据的一致性,避免在数据修改时出现异常情况。
实际开发中是否一定要严格遵循三范式
实际开发中,并不一定严格遵循三范式。虽然三范式能保证数据的规范性,但在实际工作中,性能也是重要考量因素。例如,某些场景下严格遵循三范式可能需要多表联查,而多表联查在数据量较大时效率较低。为了提升查询性能,有时会引入冗余字段,将数据存储在更少的表中,这是典型的空间换时间策略。
面试题二:关系型数据库与非关系数据库的区别及应用场景
关系型数据库
关系型数据库基于关系模型,以表格结构组织和存储数据,数据按行和列存储,可通过主键和外键建立表间关系。
其特点包括:
- 统一的数据结构:以表格形式存储,每列有特定数据类型,提供规范、结构化的数据存储方式。
- 强一致性:遵循 ACID 原则(原子性、一致性、隔离性、持久性),保障数据一致性和事务完整性。
- 数据完整性:支持通过主键和外键定义表间关联关系,进行数据完整性约束。
- 丰富的查询功能:借助 SQL 查询语言,可进行复杂的关系查询、连接操作、多表查询、条件查询和聚合查询等。代表数据库有 MySQL、Oracle 等。
非关系型数据库
非关系型数据库(NoSQL)不同于传统关系型数据库,不依赖表格和关系模型,采用键值对、文档、图等多种数据模型存储和管理数据,放宽了对数据一致性的要求。
其特点如下:
- 灵活的数据模型:可根据应用需求选择和定制合适的数据模型,如键值对形式。
- 高可扩展:天生支持分布式计算和存储,便于横向扩展,应对大规模数据和高并发访问。
- 高性能和高可用:由于放宽一致性要求,可进行异步读写和读写分离等优化,提升性能和可用性。代表数据库有 Redis、MongoDB、Neo4j 等。
两者区别
- 数据模型不同:关系型数据库基于关系模型,以表格存储数据,表间通过外键关联;非关系型数据库不采用表格和关系模型,数据存储形式多样。
- 数据结构不同:关系型数据库数据结构严格,需预先定义结构和字段类型,数据修改遵循规范和约束;非关系型数据库数据结构灵活,无需预先定义严格模式,可随时添加或修改数据结构。
- 查询语言不同:关系型数据库常用 SQL 查询,支持复杂查询条件、连接操作和聚合函数;非关系型数据库查询语言因类型而异,部分支持类似 SQL 语法,部分使用特定 API 或 DSL。
- 事务支持不同:关系型数据库通常支持 ACID 事务特征,保证数据一致性和完整性;非关系型数据库事务支持程度不同,多数只提供部分 ACID 特性或采用不同一致性模型。
- 扩展性与性能不同:传统关系型数据库水平扩展存在挑战,常通过垂直扩展提升性能;非关系型数据库设计更易于水平扩展,通过增加服务器分散数据和负载。
应用场景
- 关系型数据库:适用于对数据一致性要求高、查询复杂的场景,如金融交易系统、企业级应用、内容管理系统等。
- 非关系型数据库:适用于海量数据存储、日志系统、大数据分析、实时处理、Web 应用和移动应用等领域,处理半结构化和非结构化数据时优势明显。
面试题三:MySQL 常用引擎
存储引擎决定了数据的存储方式、索引建立方式以及数据更新和查询的技术实现。在 MySQL 中,常用的存储引擎有以下几种:
- InnoDB:MySQL 5.5 + 版本的默认存储引擎,支持事务处理、行级锁定和物理外键约束。特点是能提供良好的数据一致性、崩溃恢复能力和高并发性能,适用于需要事务支持和多用户读写操作的应用场景。
- MyISAM:MySQL 早期的默认存储引擎,不支持事务和行级锁定。它的优势是读取速度快,数据存储文件较小,适用于只读或读多写少、不需要事务的场景。
- MEMORY:将表数据存储在内存中,提供极快的访问速度,但数据在服务器重启后会丢失。常用于临时表、缓存表或需要快速查询的小型表。
面试题四:InnoDB 和 MyISAM 的区别
- 事务支持不同:InnoDB 支持事务,能保证数据的一致性和完整性;MyISAM 不支持事务。
- 锁粒度不同:InnoDB 最小锁粒度为行级锁,在并发操作时,仅锁定操作的行,对其他行的影响小,可提高并发性能,但锁管理开销较大;MyISAM 最小锁粒度是表级锁,操作时锁定整个表,其他读写操作需等待锁释放,并发性能较低,但锁管理开销小。
- 外键支持不同:InnoDB 支持物理外键,可建立表间的关联约束;MyISAM 不支持物理外键。
- 索引存储方式不同:InnoDB 索引叶子节点存储的是当前行的数据;MyISAM 索引的叶子节点存储的是地址,需根据地址获取当前行数据。
面试题五:阿里巴巴《Java 开发手册》不建议使用物理外键的原因
使用物理外键会带来以下问题:
- 性能问题:插入数据前需先到主键表中查询,增加了数据库的 I/O 操作和查询时间,导致性能下降。
- 数据库更新风暴问题:在高并发场景下,可能引发数据库更新风暴,大量并发的数据库更新操作集中发生,使数据库服务器承受巨大压力,导致性能瓶颈、延迟增大甚至系统崩溃。
面试题六:物理删除和逻辑删除的区别及日常开发选择
- 物理删除:直接从数据库中永久删除数据记录,释放相关存储空间,被删除数据无法恢复,原有的唯一标识也不再存在。
- 逻辑删除:在程序中实现删除功能,通常通过添加标记字段或状态字段,将数据标记为已删除状态,数据实际仍存于数据库中,可通过修改查询语句筛选出删除或未删除状态的数据。
在日常开发中,选择哪种删除方式取决于具体需求和业务场景。对于重要数据,在数据库空间和性能允许的情况下,多采用逻辑删除,这样既能保留历史数据,又方便后续数据恢复,保证数据完整性;对于不重要的数据,如具有时效性的日志数据,且数据库对性能和空间有要求时,会使用物理删除以节省系统空间,提高查询性能。
面试题七:内连接、外连接和自连接
- 内连接:是最常用的连接类型,根据两个或多个表之间的共同列值连接表,只有当连接表之间存在匹配值时才返回结果。例如:
SELECT 列名 FROM 表1 INNER JOIN 表2 ON 表1.列 = 表2.列;
- 外连接:可返回连接表之间所有匹配和不匹配的数据。外连接分为左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。例如:
SELECT 列名 FROM 表1 LEFT OUTER JOIN 表2 ON 表1.列 = 表2.列;
内连接返回的是两个表都存在的数据;左(右)外连接是左(右)表的所有数据和右(左)表匹配的数据;全外连接返回两个表的所有数据,包括匹配和不匹配的数据。
这里我借用一下我觉得比较直观的图片,它们的区别是:内连接返回的是两个表都存在的数据,如图:
左(右)外连接是左(右)表的所有数据和右(左)表匹配的数据,如图:
全外查询到的数据,如图:
- 自连接:是一种特殊的表连接,连接的表在物理上为同一张表,但逻辑上视为多张表,常用于处理表中具有层次结构的数据。假设存在一个员工表:
员工 ID | 姓名 | 经理 ID |
---|---|---|
1 | 张三 | 3 |
2 | 李四 | 3 |
3 | 王五 | NULL |
4 | 赵六 | 1 |
通过自连接可查询每个员工的经理姓名:
SELECT e1.姓名 AS 员工姓名, e2.姓名 AS 经理姓名
FROM 员工表 AS e1
JOIN 员工表 AS e2 ON e1.经理ID = e2.员工ID;
结果如下:
员工姓名 | 经理姓名 |
---|---|
张三 | 王五 |
李四 | 王五 |
赵六 | 张三 |
面试题八:创建索引时是否锁表
在 MySQL 5.7 之前,创建索引会锁表。因为创建索引过程中,需保证表数据不被修改,以确保索引的正确性和一致性,这会导致其他会话(除 select 外)阻塞。
而在 MySQL 5.7 之后,引入了 Online DDL 技术,允许创建索引时不阻塞其他会话,所有 DML(INSERT、UPDATE、DELETE、SELECT)操作可并发执行。该技术使数据库在运行期间能执行表结构或其他数据库对象的更改操作,无需中断正在进行的事务和查询。
面试题九:聚簇索引和非聚簇索引的区别
- 聚簇索引:数据按照索引列的值顺序存储在同一页上,索引和数据存储在一起,找到索引就能找到数据。在 MySQL 的 InnoDB 引擎中,聚簇索引默认是主键。
- 非聚簇索引:将索引和数据行分开存储,索引结构的叶子节点指向数据对应的位置,叶子节点存储的是主键 ID。使用非聚簇索引查询时,先得到主键 ID,再通过主键 ID 到聚簇索引上查找真正的行数据,这个过程称为回表查询。
两者主要区别如下:
- 聚簇索引叶子节点存储行数据,非聚簇索引叶子节点存储聚簇索引(通常是主键 ID)。
- 聚簇索引查询效率更高,非聚簇索引需回表查询,性能相对较低。
- 聚簇索引一般为主键索引,一个表中只能有一个;非聚簇索引一个表中可以有多个。
面试题十:聚簇索引与主键索引的关系及生成规则
聚簇索引在大多数有主键的情况下等于主键索引。若表中没有主键索引,聚簇索引的生成规则如下:
- 无主键索引,则使用非空唯一索引:若表中无主键索引,InnoDB 会使用第一个满足唯一约束且设置了非空约束的索引作为聚簇索引。
- 无任何满足的索引,则生成隐藏聚簇索引:若表中既无主键索引,也无符合条件的唯一索引,InnoDB 会生成一个名为 GEN_CLUST_INDEX 的隐藏聚簇索引,该索引为六字节长整型类型。
通过对这些面试题的深入理解,我们不仅能在面试中脱颖而出,更能在实际数据库开发和管理工作中做出更合理的决策,提升系统性能和稳定性。