文章目录
-
- 1 MySQL 基础
-
- 1.1 什么是 ER 图?
- 1.2 数据库范式了解吗?
- 1.3 为什么不推荐使用外键与级联?
- 1.4 drop、delete 与 truncate 区别?
- 1.5 什么是关系型数据库?
- 1.6 MySQL 字段类型有哪些
- 1.7 CHAR 和 VARCHAR 的区别是什么?
- 1.8 VARCHAR(100)和 VARCHAR(10)的区别是什么?
- 1.9 DECIMAL 和 FLOAT/DOUBLE 的区别是什么?
- 1.10 为什么不推荐使用 TEXT 和 BLOB?
- 1.11 DATETIME 和 TIMESTAMP 的区别是什么?
- 1.12 NULL 和 '' 的区别是什么?
- 1.13 Boolean 类型如何表示?
- 1.14 MySQL 支持哪些存储引擎?默认使用哪个?
- 1.15 MySQL 存储引擎架构了解吗?
- 1.16 MyISAM 和 InnoDB 有什么区别?🔥
- 1.17 执行一条 SQL 查询语句,期间发生了什么?🔥
- 1.18 MySQL 的 NULL 值是怎么存放的?
- 1.19 MySQL 怎么知道 varchar(n) 实际占用数据的大小?
- 1.20 varchar(n) 中 n 最大取值为多少?
- 1.21 行溢出后,MySQL 是怎么处理的?
- 1.22 MySQL 怎么连表查询?🔥
- 1.23 MySQL的关键字in和exist
- 1.24 mysql中的一些基本函数,你知道哪些?
- 2 MySQL 索引
- 3 MySQL 事务
- 4 日志
- 5 MySQL 锁
- 6 MySQL 性能优化
本文作者:夏日。主要参考:JavaGuide、小林coding和二哥的Java进阶之路,同时加上网上搜索整理和个人理解总结。
1 MySQL 基础
1.1 什么是 ER 图?
ER 图 全称是 Entity Relationship Diagram(实体联系图),提供了表示实体类型、属性和联系的方法。
- 实体:通常是现实世界的业务对象,当然使用一些逻辑对象也可以,实体使用矩形框表示。
- 属性:即某个实体拥有的属性,可以理解为字段,属性使用椭圆形表示。
- 联系:即实体与实体之间的关系,用菱形表示,这个关系不仅有业务关联关系,还能通过数字表示实体之间的数量对照关系。
下图是一个学生选课的 ER 图,每个学生可以选若干门课程,同一门课程也可以被若干人选择,所以它们之间的关系是多对多(M: N)。另外,还有其他两种实体之间的关系是:1 对 1(1:1)、1 对多(1: N)。
1.2 数据库范式了解吗?
- 1NF(第一范式):数据库表的每一列都是不可分割的原子数据项。1NF 是所有关系型数据库的最基本要求。
- 2NF(第二范式):在1NF 基础上消除了非主属性对主码的部分函数依赖,也就是需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关。
- 3NF(第三范式):要求任何非主属性不依赖于其它非主属性。
1.3 为什么不推荐使用外键与级联?
对于外键和级联,阿里巴巴开发手册这样说到:
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
说明: 以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度
为什么不要用外键呢?大部分人可能会这样回答:
- 增加了复杂性: 外键是固定的,假如哪天需求有变化,数据库中的这个字段根本不需要和其他表有关联的话就会增加很多麻烦。
- 对分库分表不友好:因为分库分表下外键是无法生效的。
- 级联更新是强阻塞,存在数据库更新风暴的风险
- 外键影响数据库的插入速度
1.4 drop、delete 与 truncate 区别?
1.4.1 用法不同
drop
(丢弃数据):drop table 表名
,直接将表都删除掉,在删除表的时候使用。truncate
(清空数据) :truncate table 表名
,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。delete
(删除数据) :delete from 表名 where 列名=值
,删除某一行的数据,如果不加where
子句和truncate table 表名
作用类似。
truncate
和不带 where
子句的 delete
、以及 drop
都会删除表内的数据,但是 truncate
和 delete
只删除数据不删除表的结构(定义),执行 drop
语句,此表的结构也会删除,也就是执行 drop
之后对应的表不复存在。
1.4.2 属于不同的数据库语言
truncate
和 drop
属于 DDL(数据定义语言)语句,操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。而 delete
语句是 DML (数据库操作语言)语句,这个操作会放到 rollback segment 中,事务提交之后才生效。
DML 语句和 DDL 语句区别:
- DML 是数据库操作语言(Data Manipulation Language)的缩写,是指对数据库中表记录的操作,主要包括表记录的插入、更新、删除和查询,是开发人员日常使用最频繁的操作。
- DDL (Data Definition Language)是数据定义语言的缩写,涉及到表的定义、结构的修改。DDL 语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用。
另外,由于 select
不会对表进行破坏,所以有的地方也会把 select
单独区分开叫做数据库查询语言 DQL(Data Query Language)。
1.5 什么是关系型数据库?
关系型数据库(RDB,Relational Database)就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多)。
关系型数据库中,我们的数据都被存放在了各种表中(比如用户表),表中的每一行就存放着一条数据(比如一个用户的信息)。
1.6 MySQL 字段类型有哪些
MySQL 字段类型可以简单分为三大类:
- 数值类型:整型(TINYINT、SMALLINT、MEDIUMINT、INT 和 BIGINT)、浮点型(FLOAT 和 DOUBLE)、定点型(DECIMAL)
- 字符串类型:CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB 等,最常用的是 CHAR 和 VARCHAR。
- 日期时间类型:YEAR、TIME、DATE、DATETIME 和 TIMESTAMP 等。
1.7 CHAR 和 VARCHAR 的区别是什么?
- CHAR是固定长度的字符串类型,定义时需要指定固定长度,存储时会在末尾补足空格,检索时会去掉空格。
- CHAR适合存储长度固定的数据,如固定长度的代码、状态等,存储空间固定,对于短字符串效率较高。
- VARCHAR是可变长度的字符串类型,定义时需要指定最大长度,实际存储时根据实际长度占用存储空间,且需要使用 1 或 2 个额外字节记录字符串的长度。
- VARCHAR适合存储长度可变的数据,如用户输入的文本、备注等,节约存储空间。
1.8 VARCHAR(100)和 VARCHAR(10)的区别是什么?
VARCHAR(100)和 VARCHAR(10)都是变长类型,表示能存储最多 100 个字符和 10 个字符。因此,VARCHAR (100) 可以满足更大范围的字符存储需求,有更好的业务拓展性。而 VARCHAR(10)存储超过 10 个字符时,就需要修改表结构才可以。
虽说 VARCHAR(100)和 VARCHAR(10)能存储的字符范围不同,但二者存储相同的字符串,所占用磁盘的存储空间其实是一样的,这也是很多人容易误解的一点。
不过,VARCHAR(100) 会消耗更多的内存。这是因为 VARCHAR 类型在内存中操作时,通常会分配固定大小的内存块来保存值,即使用字符类型中定义的长度。例如在进行排序的时候,VARCHAR(100)是按照 100 这个长度来进行的,也就会消耗更多内存。
1.9 DECIMAL 和 FLOAT/DOUBLE 的区别是什么?
DECIMAL 是定点数,FLOAT/DOUBLE 是浮点数。DECIMAL 可以存储精确的小数值,FLOAT/DOUBLE 只能存储近似的小数值。
DECIMAL 用于存储具有精度要求的小数,例如与货币相关的数据,可以避免浮点数带来的精度损失。
在 Java 中,MySQL 的 DECIMAL 类型对应的是 Java 类 java.math.BigDecimal
。
1.10 为什么不推荐使用 TEXT 和 BLOB?
TEXT 类型类似于 CHAR(0-255 字节)和 VARCHAR(0-65,535 字节),但可以存储更长的字符串,即长文本数据,例如博客内容。
BLOB 类型主要用于存储二进制大对象,例如图片、音视频等文件。
在日常开发中,很少使用 TEXT 类型,但偶尔会用到,而 BLOB 类型则基本不常用。如果预期长度范围可以通过 VARCHAR 来满足,建议避免使用 TEXT。
数据库规范通常不推荐使用 BLOB 和 TEXT 类型,这两种类型具有一些缺点和限制,例如:
- 不能有默认值。
- 在使用临时表时无法使用内存临时表,只能在磁盘上创建临时表(《高性能 MySQL》书中有提到)。
- 检索效率较低。
- 不能直接创建索引,需要指定前缀长度。
- 可能会消耗大量的网络和 IO 带宽。
- 可能导致表上的 DML 操作变慢。
- ……
1.11 DATETIME 和 TIMESTAMP 的区别是什么?
DATETIME 类型没有时区信息,TIMESTAMP 和时区有关。
TIMESTAMP 只需要使用 4 个字节的存储空间,但是 DATETIME 需要耗费 8 个字节的存储空间。但是,这样同样造成了一个问题,Timestamp 表示的时间范围更小。
- DATETIME:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
- Timestamp:1970-01-01 00:00:01 ~ 2037-12-31 23:59:59
1.12 NULL 和 ‘’ 的区别是什么?
为什么 MySQL 不建议使用
NULL
作为列默认值?
NULL
跟 ''
(空字符串)是两个完全不一样的值,区别如下:
NULL
代表一个不确定的值,就算是两个NULL
,它俩也不一定相等。例如,SELECT NULL=NULL
的结果为 false,但是在我们使用DISTINCT
,GROUP BY
,ORDER BY
时,NULL
又被认为是相等的。''
的长度是 0,是不占用空间的,而NULL
是需要占用空间的。NULL
会影响聚合函数的结果。例如,SUM
、AVG
、MIN
、MAX
等聚合函数会忽略NULL
值。COUNT
的处理方式取决于参数的类型。如果参数是*
(COUNT(*)
),则会统计所有的记录数,包括NULL
值;如果参数是某个字段名(COUNT(列名)
),则会忽略NULL
值,只统计非空值的个数。- 查询
NULL
值时,必须使用IS NULL
或IS NOT NULLl
来判断,而不能使用 =、!=、 <、> 之类的比较运算符。而''
是可以使用这些比较运算符的。
1.13 Boolean 类型如何表示?
MySQL 中没有专门的布尔类型,而是用 TINYINT(1) 类型来表示布尔值