上次写的java八股收到了很多uu的关注,很开心捏!!(^▽^ )
鼠鼠好像找到流量密码了。这次把数据库的八股也整理出来了,因为看八股的时候比较喜欢深究(好像是坏习惯T.T),所以学的比较慢。后续我也会继续整理其他java开发技术栈的八股滴~之前发过的八股也会随笔记持续更新,要点赞收藏关注哦,哦内盖西马斯!
数据库基础知识
什么是元组, 码, 候选码, 主码, 外码, 主属性, 非主属性?
- 元组:元组(tuple)是关系数据库中的基本概念,关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组,每列就是一个属性。 在二维表里,元组也称为行。
- 码:码就是能唯一标识实体的属性,对应表中的列。
- 候选码:若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何、子集都不能再标识,则称该属性组为候选码。例如:在学生实体中,"学号"是能唯一的区分学生实体的,同时又假设"姓名"、"班级"的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是候选码。
- 主码 : 主码也叫主键。主码是从候选码中选出来的。 一个实体集中只能有一个主码,但可以有多个候选码。
- 外码 : 外码也叫外键。如果一个关系中的一个属性是另外一个关系中的主码则这个属性为外码。
- 主属性:候选码中出现过的属性称为主属性。比如关系 工人(工号,身份证号,姓名,性别,部门). 显然工号和身份证号都能够唯一标示这个关系,所以都是候选码。工号、身份证号这两个属性就是主属性。如果主码是一个属性组,那么属性组中的属性都是主属性。
- 非主属性: 不包含在任何一个候选码中的属性称为非主属性。比如在关系------学生(学号,姓名,年龄,性别,班级)中,主码是"学号",那么其他的"姓名"、"年龄"、"性别"、"班级"就都可以称为非主属性。
ER 图
三要素:
- 实体:矩形框
- 属性:椭圆形
- 联系:菱形
数据库范式
第一范式
属性(对应于表中的字段)不能再被分割,也就是这个字段只能是一个值,不能再分为多个其他的字段了。1NF 是所有关系型数据库的最基本要求 ,也就是说关系型数据库中创建的表一定满足第一范式。
第二范式
2NF 在 1NF 的基础之上,消除了非主属性对于码的部分函数依赖。如下图,第二范式在第一范式的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。
- 函数依赖: 若在一张表中,在属性(或属性组)X 的值确定的情况下,必定能确定属性 Y 的值,那么就可以说 Y 函数依赖于 X,写作 X → Y
-
- 部分函数依赖: 如果 X→Y,并且存在 X 的一个真子集 X0,使得 X0→Y,则称 Y 对 X 部分函数依赖。比如学生基本信息表 R 中(学号,身份证号,姓名)当然学号属性取值是唯一的,在 R 关系中,(学号,身份证号)->(姓名),(学号)->(姓名),(身份证号)->(姓名);所以姓名部分函数依赖于(学号,身份证号);
- 完全函数依赖: 在一个关系中,若某个非主属性数据项依赖于全部关键字称之为完全函数依赖。比如学生基本信息表 R(学号,班级,姓名)假设不同的班级学号有相同的,班级内学号不能相同,在 R 关系中,(学号,班级)->(姓名),但是(学号)->(姓名)不成立,(班级)->(姓名)不成立,所以姓名完全函数依赖与(学号,班级);
- 传递函数依赖:在关系模式 R(U)中,设 X,Y,Z 是 U 的不同的属性子集,如果 X 确定 Y、Y 确定 Z,且有 X 不包含 Y,Y 不确定 X,(X∪Y)∩Z=空集合,则称 Z 传递函数依赖于 X。传递函数依赖会导致数据冗余和异常。传递函数依赖的 Y 和 Z 子集往往同属于某一个事物,因此可将其合并放到一个表中。比如在关系 R(学号 , 姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖。
第三范式
3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖 。符合 3NF 要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。比如在关系 R(学号 , 姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖,所以该表的设计,不符合 3NF 的要求。
为什么不推荐使用外键和级联?
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
说明: 以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度
- 增加复杂性:对数据作更新的时候要考虑外键约束,很麻烦
- 增加额外工作:对数据作更新时需要触发相关操作去检查,来保证数据的一致性
- 分库分表无法生效
好处也有:
- 保证数据库数据的一致性
- 级联操作方便,减少程序代码量
存储过程
阿里巴巴 Java 开发手册里禁止使用。
好处:
- 应对复杂业务非常好用,而且具有复用性。
- 存储过程都是预编译过的,比单纯sql语句更快。
坏处:
- 难以调试和扩展
- 没有移植性
- 还会消耗数据库资源
drop,delete和truncate区别
- drop(丢弃数据): drop table 表名 ,直接将表都删除掉,在删除表的时候使用。
- truncate (清空数据) : truncate table 表名 ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。
- delete(删除数据) : delete from 表名 where 列名=值,删除某一行的数据,如果不加 where 子句和truncate table 表名作用类似。
属于不同的数据库语言
truncate 和 drop 属于 DDL(数据定义语言)语句,操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。而 delete 语句是 DML (数据库操作语言)语句,这个操作会放到 rollback segment 中,事务提交之后才生效。
数据库设计通常分为哪几步?
- 需求分析 : 分析用户的需求,包括数据、功能和性能需求。
- 概念结构设计 : 主要采用 E-R 模型进行设计,包括画 E-R 图。
- 逻辑结构设计 : 通过将 E-R 图转换成表,实现从 E-R 模型到关系模型的转换。
- 物理结构设计 : 主要是为所设计的数据库选择合适的存储结构和存取路径。
- 数据库实施 : 包括编程、测试和试运行
- 数据库的运行和维护 : 系统的运行与数据库的日常维护。
NoSQL
定义:非关系型数据库。
场景:
- 键值
- 文档
- 图形类型数据
好处:
- 灵活:数据模型很灵活,适用于半结构化和非结构化的数据使用。
- 可扩展性:支持分布式硬件集群横向扩展,不止于改用性能更nb的服务器来纵向扩展
- 高性能:对特定数据模型有优化。
- 功能丰富:有专门针对各自数据模型的api和数据类型。
SQL 和 NoSQL 有什么区别?
NoSQL 数据库有哪些类型?
- 键值:redis和DynanoDB
- 文档: MongoDB
- 图形:Neo4j和Giraph
- 宽列:Cassandra和HBase
字符集
定义:一系列字符的集合。
计算机只能存储二进制的数据,那英文、汉字、表情等字符应该如何存储呢?
我们要将这些字符和二进制的数据一一对应起来,比如说字符"a"对应"01100001",反之,"01100001"对应 "a"。我们将字符对应二进制数据的过程称为"字符编码 ",反之,二进制数据解析成字符的过程称为"字符解码"。
常见字符集:
- ASCII
- GB2312
- GBK
- Unicode
不同字符集区别在于表示范围 和编码方式
字符编码
每种字符集都有自己的字符编码规则,常用的字符集编码规则有 ASCII 编码、 GB2312 编码、GBK 编码、GB18030 编码、Big5 编码、UTF-8 编码、UTF-16 编码等。
ASCII
一个ASCII码长度是一个字节,但最高位是0,作为奇偶校验位,来验证数据传输过程,所以它实际只能定义128个字符。
ASCII扩展字符集: 用8bit表示一个字符,可以定义256个字符。
GB2312
覆盖绝大多数常用汉字,但不支持很多生僻字和繁体字。
对于英语字符,是1字节编码;非英字符,要2字节编码。
GBK
可以看作是 GB2312 字符集的扩展,兼容 GB2312 字符集,共收录了 20000 多个汉字。"K"指"扩展"的"扩"字 首字母。
GB18030
GB18030 完全兼容 GB2312 和 GBK 字符集,纳入中国国内少数民族的文字,且收录了日韩汉字,是目前为止最全面的汉字字符集,共收录汉字 70000 多个。
BIG5
BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
Unicode & UTF-8
Unicode 字符集中包含了世界上几乎所有已知的字符。不过,Unicode 字符集并没有规定如何存储这些字符(也就是如何使用二进制数据表示这些字符)。
UTF-8 (8-bit Unicode Transformation Format)使用1-4字节为每个字符编码,UTF-16 使用 2 或 4 个字节为每个字符编码,UTF-32 固定位 4 个字节为每个字符编码。
UTF-8 可以根据不同的符号自动选择编码的长短,像英文字符只需要 1 个字节就够了,这一点 ASCII 字符集一样 。因此,对于英语字符,UTF-8 编码和 ASCII 码是相同的。
UTF-32 的规则最简单,不过缺陷也比较明显,对于英文字母这类字符消耗的空间是 UTF-8 的 4 倍之多。UTF-8 是目前使用最广的一种字符编码。
通常情况下,我们建议使用 UTF-8 作为默认的字符编码方式。
MySQL 字符编码集中有两套 UTF-8 编码实现:
- utf8:utf8编码只支持1-3个字节 。 在 utf8 编码中,中文是占 3 个字节,其他数字、英文、符号占一个字节。但 emoji 符号占 4 个字节,一些较复杂的文字、繁体字也是 4 个字节。
- utf8mb4:UTF-8 的完整实现,正版!最多支持使用 4 个字节表示字符,因此,可以用来存储 emoji 符号。
因此,如果你需要存储emoji类型的数据或者一些比较复杂的文字、繁体字到 MySQL 数据库的话,数据库的编码一定要指定为utf8mb4 而不是utf8 ,要不然存储的时候就会报错了。
MySQL 字符集
查看支持的字符集
show charset
命令查看,支持like 和 where
默认字符集
在 MySQL5.7 中,默认字符集是 latin1 ;在 MySQL8.0 中,默认字符集是 utf8mb4
字符集的层次级别
MySQL 中的字符集有以下的层次级别:
- server(MySQL 实例级别)
- database(库级别)
- table(表级别)
- column(字段级别)
它们的优先级可以简单的认为是从上往下依次增大,也即 column
的优先级会大于 table
等其余层次的。如指定 MySQL 实例级别字符集是utf8mb4
,指定某个表字符集是latin1
,那么这个表的所有字段如果不指定的话,编码就是latin1
。
server
不同版本的 MySQL 其 server 级别的字符集默认值不同,在 MySQL5.7 中,其默认值是 latin1
;在 MySQL8.0 中,其默认值是 utf8mb4
database
database 级别的字符集是我们在创建数据库和修改数据库时指定的:
sql
CREATE DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
ALTER DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
如前面所说,如果在执行上述语句时未指定字符集,那么 MySQL 将会使用 server 级别的字符集。
可以通过下面的方式查看某个数据库的字符集:
scss
USE db_name;
SELECT @@character_set_database, @@collation_database;
table
table
级别的字符集是在创建表和修改表时指定的:
sql
CREATE TABLE tbl_name (column_list)
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]]
ALTER TABLE tbl_name
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]
column
column
级别的字符集同样是在创建表和修改表时指定的,只不过它是定义在列中。下面是个例子:
sql
CREATE TABLE t1
(
col1 VARCHAR(5)
CHARACTER SET latin1
COLLATE latin1_german1_ci
);
如果未指定列级别的字符集,那么将会使用表级别的字符集。
连接字符集
前面说到了字符集的层次级别,它们是和存储相关的。而连接字符集涉及的是和 MySQL 服务器的通信。连接字符集与下面这几个变量息息相关:
- character_set_client :描述了客户端发送给服务器的 SQL 语句使用的是什么字符集。
- character_set_connection :描述了服务器接收到 SQL 语句时使用什么字符集进行翻译
- character_set_results :描述了服务器返回给客户端的结果使用的是什么字符集。
它们的值可以通过下面的 SQL 语句查询:
sql
SELECT * FROM performance_schema.session_variables
WHERE VARIABLE_NAME IN (
'character_set_client', 'character_set_connection',
'character_set_results', 'collation_connection'
) ORDER BY VARIABLE_NAME;
sql
SHOW SESSION VARIABLES LIKE 'character_set_%';
如果要想修改前面提到的几个变量的值,有以下方式:
1、修改配置文件
csharp
[mysql]
# 只针对MySQL客户端程序
default-character-set=utf8mb4
2、使用 SQL 语句
bash
set names utf8mb4
# 或者一个个进行修改
# SET character_set_client = utf8mb4;
# SET character_set_results = utf8mb4;
# SET collation_connection = utf8mb4;