Skip to content

Commit 763d099

Browse files
committed
Update mysql-questions-01.md
1 parent 24e50ac commit 763d099

File tree

1 file changed

+56
-44
lines changed

1 file changed

+56
-44
lines changed

docs/database/mysql/mysql-questions-01.md

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ MySQL 主要具有下面这些优点:
7474

7575
MySQL 字段类型可以简单分为三大类:
7676

77-
- **数值类型**:整型(tinyint、smallint、mediumint、intbigint)、浮点型(floatdouble)、定点型(decimal
78-
- **字符串类型**char、varchar、tinytext、text、mediumtext、longtext、tinyblob、blob、mediumbloblongblob 等,最常用的是 charvarchar
79-
- **日期时间类型**year、time、date、datetimetimestamp 等。
77+
- **数值类型**:整型(TINYINT、SMALLINT、MEDIUMINT、INTBIGINT)、浮点型(FLOATDOUBLE)、定点型(DECIMAL
78+
- **字符串类型**CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、TINYBLOB、BLOB、MEDIUMBLOBLONGBLOB 等,最常用的是 CHARVARCHAR
79+
- **日期时间类型**YEAR、TIME、DATE、DATETIMETIMESTAMP 等。
8080

8181
下面这张图不是我画的,忘记是从哪里保存下来的了,总结的还蛮不错的。
8282

@@ -86,71 +86,79 @@ MySQL 字段类型比较多,我这里会挑选一些日常开发使用很频
8686

8787
另外,推荐阅读一下《高性能 MySQL(第三版)》的第四章,有详细介绍 MySQL 字段类型优化。
8888

89-
### char 和 varchar 的区别是什么
89+
### 整数类型的 UNSIGNED 属性有什么用
9090

91-
char 和 varchar 是最常用到的字符串类型,两者的主要区别在于:**char 是定长字符串,varchar 是变长字符串。**
91+
MySQL 中的整数类型可以使用可选的 UNSIGNED 属性来表示不允许负值的无符号整数。使用 UNSIGNED 属性可以将正整数的上限提高一倍,因为它不需要存储负数值。
9292

93-
char 在存储时会在右边填充空格以达到指定的长度,检索时会去掉空格;varchar 在存储时需要使用 1 或 2 个额外字节记录字符串的长度,检索时不需要处理
93+
例如, TINYINT UNSIGNED 类型的取值范围是 0 ~ 255,而普通的 TINYINT 类型的值范围是 -128 ~ 127。INT UNSIGNED 类型的取值范围是 0 ~ 4,294,967,295,而普通的 TINYINT 类型的值范围是 2,147,483,648 ~ 2,147,483,647
9494

95-
char 更适合存储长度较短或者长度都差不多的字符串,例如 Bcrypt 算法、MD5 算法加密后的密码、身份证号码。varchar 类型适合存储长度不确定或者差异较大的字符串,例如用户昵称、文章标题等
95+
对于从 0 开始递增的 ID 列,使用 UNSIGNED 属性可以非常适合,因为不允许负值并且可以拥有更大的上限范围,提供了更多的 ID 值可用
9696

97-
char(M) 和 varchar(M) 的 M 都代表能够保存的字符数的最大值,无论是字母、数字还是中文,每个都只占用一个字符。
97+
### CHAR 和 VARCHAR 的区别是什么?
9898

99-
### varchar(100)和 varchar(10)的区别是什么?
99+
CHAR 和 VARCHAR 是最常用到的字符串类型,两者的主要区别在于:**CHAR 是定长字符串,VARCHAR 是变长字符串。**
100100

101-
varchar(100)和 varchar(10)都是变长类型,表示能存储最多 100 个字符和 10 个字符。因此,varchar (100) 可以满足更大范围的字符存储需求,有更好的业务拓展性。而 varchar(10)存储超过 10 个字符时,就需要修改表结构才可以
101+
CHAR 在存储时会在右边填充空格以达到指定的长度,检索时会去掉空格;VARCHAR 在存储时需要使用 1 或 2 个额外字节记录字符串的长度,检索时不需要处理
102102

103-
虽说 varchar(100)和 varchar(10)能存储的字符范围不同,但二者存储相同的字符串,所占用磁盘的存储空间其实是一样的,这也是很多人容易误解的一点
103+
CHAR 更适合存储长度较短或者长度都差不多的字符串,例如 Bcrypt 算法、MD5 算法加密后的密码、身份证号码。VARCHAR 类型适合存储长度不确定或者差异较大的字符串,例如用户昵称、文章标题等
104104

105-
不过,varchar(100)会消耗更多的内存。这是因为 varchar 类型在内存中操作时,通常会分配固定大小的内存块来保存值,即使用字符类型中定义的长度。例如在进行排序的时候,varcahr(100)是按照 100 这个长度来进行的,也就会消耗更多内存
105+
CHAR(M) 和 VARCHAR(M) 的 M 都代表能够保存的字符数的最大值,无论是字母、数字还是中文,每个都只占用一个字符
106106

107-
### decimal 和 float/double 的区别是什么?
107+
### VARCHAR(100)和 VARCHAR(10)的区别是什么?
108108

109-
decimal 和 float 的区别是:**decimal 是定点数,float/double 是浮点数。decimal 可以存储精确的小数值,float/double 只能存储近似的小数值。**
109+
VARCHAR(100)和 VARCHAR(10)都是变长类型,表示能存储最多 100 个字符和 10 个字符。因此,VARCHAR (100) 可以满足更大范围的字符存储需求,有更好的业务拓展性。而 VARCHAR(10)存储超过 10 个字符时,就需要修改表结构才可以。
110110

111-
decimal 用于存储有精度要求的小数比如与金钱相关的数据,可以避免浮点数带来的精度损失
111+
虽说 VARCHAR(100)和 VARCHAR(10)能存储的字符范围不同,但二者存储相同的字符串,所占用磁盘的存储空间其实是一样的,这也是很多人容易误解的一点
112112

113-
在 Java 中,MySQL 的 decimal 类型对应的是 Java 类 `java.math.BigDecimal`
113+
不过,VARCHAR(100) 会消耗更多的内存。这是因为 VARCHAR 类型在内存中操作时,通常会分配固定大小的内存块来保存值,即使用字符类型中定义的长度。例如在进行排序的时候,VARCHAR(100)是按照 100 这个长度来进行的,也就会消耗更多内存
114114

115-
### 为什么不推荐使用 text 和 blob
115+
### DECIMAL 和 FLOAT/DOUBLE 的区别是什么
116116

117-
text 类型类似于 char(0 - 255 字节)、varchar(0 - 65 535 字节),不过其可以存储更长的字符串,也就是长文本数据,比如一篇博客的内容。
117+
DECIMAL 和 FLOAT 的区别是:**DECIMAL 是定点数,FLOAT/DOUBLE 是浮点数。DECIMAL 可以存储精确的小数值,FLOAT/DOUBLE 只能存储近似的小数值。**
118118

119-
| **类型** | **可存储大小** | **用途** |
120-
| ---------- | ---------------------- | -------------- |
121-
| TINYTEXT | 0 - 255 字节 | 一般文本字符串 |
122-
| TEXT | 0 - 65 535 字节 | 长文本字符串 |
123-
| MEDIUMTEXT | 0 - 16 772 150 字节 | 较大文本数据 |
124-
| LONGTEXT | 0 - 4 294 967 295 字节 | 极大文本数据 |
119+
DECIMAL 用于存储具有精度要求的小数,例如与货币相关的数据,可以避免浮点数带来的精度损失。
125120

126-
blob 类型主要用于存储二进制大对象,例如图片,音视频等文件
121+
在 Java 中,MySQL 的 DECIMAL 类型对应的是 Java 类 `java.math.BigDecimal`
127122

128-
| **类型** | **可存储大小** | **用途** |
129-
| ---------- | -------------- | ------------------------ |
130-
| TINYBLOB | 0 - 255 字节 | 短文本二进制字符串 |
131-
| BLOB | 0 - 65KB | 二进制字符串 |
132-
| MEDIUMBLOB | 0 - 16MB | 二进制形式的长文本数据 |
133-
| LONGBLOB | 0 - 4GB | 二进制形式的极大文本数据 |
123+
### 为什么不推荐使用 TEXT 和 BLOB?
134124

135-
日常开发中,text 类型用的很少,但偶尔会用,blob 类型就属于是基本不用。如果预期长度范围 varchar 就满足,就避免使用 text
125+
TEXT 类型类似于 CHAR(0-255 字节)和 VARCHAR(0-65,535 字节),但可以存储更长的字符串,即长文本数据,例如博客内容
136126

137-
数据库规范中一般不推荐使用 blob 及 text 类型,二者的部分缺点和限制如下:
127+
| 类型 | 可存储大小 | 用途 |
128+
| ---------- | -------------------- | -------------- |
129+
| TINYTEXT | 0-255 字节 | 一般文本字符串 |
130+
| TEXT | 0-65,535 字节 | 长文本字符串 |
131+
| MEDIUMTEXT | 0-16,772,150 字节 | 较大文本数据 |
132+
| LONGTEXT | 0-4,294,967,295 字节 | 极大文本数据 |
133+
134+
BLOB 类型主要用于存储二进制大对象,例如图片、音视频等文件。
135+
136+
| 类型 | 可存储大小 | 用途 |
137+
| ---------- | ---------- | ------------------------ |
138+
| TINYBLOB | 0-255 字节 | 短文本二进制字符串 |
139+
| BLOB | 0-65KB | 二进制字符串 |
140+
| MEDIUMBLOB | 0-16MB | 二进制形式的长文本数据 |
141+
| LONGBLOB | 0-4GB | 二进制形式的极大文本数据 |
142+
143+
在日常开发中,很少使用 TEXT 类型,但偶尔会用到,而 BLOB 类型则基本不常用。如果预期长度范围可以通过 VARCHAR 来满足,建议避免使用 TEXT。
144+
145+
数据库规范通常不推荐使用 BLOB 和 TEXT 类型,这两种类型具有一些缺点和限制,例如:
138146

139147
- 不能有默认值。
140-
- 在遇到使用临时表的情况时,无法使用内存临时表,只能在磁盘上创建临时表(《高性能 MySQL》这本书有提到)。
141-
- 检索效率比 char 和 varchar 低
148+
- 在使用临时表时无法使用内存临时表,只能在磁盘上创建临时表(《高性能 MySQL》书中有提到)。
149+
- 检索效率较低
142150
- 不能直接创建索引,需要指定前缀长度。
143-
- 会消耗大量的网络和 IO 带宽。
144-
- 可能会导致表上的 DML 操作都变得较慢
151+
- 可能会消耗大量的网络和 IO 带宽。
152+
- 可能导致表上的 DML 操作变慢
145153
- ......
146154

147-
### datetimetimestamp 的区别是什么?
155+
### DATETIMETIMESTAMP 的区别是什么?
148156

149-
DateTime 类型没有时区信息,Timestamp 和时区有关。
157+
DATETIME 类型没有时区信息,TIMESTAMP 和时区有关。
150158

151-
Timestamp 只需要使用 4 个字节的存储空间,但是 DateTime 需要耗费 8 个字节的存储空间。但是,这样同样造成了一个问题,Timestamp 表示的时间范围更小。
159+
TIMESTAMP 只需要使用 4 个字节的存储空间,但是 DATETIME 需要耗费 8 个字节的存储空间。但是,这样同样造成了一个问题,Timestamp 表示的时间范围更小。
152160

153-
- DateTime:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
161+
- DATETIME:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
154162
- Timestamp:1970-01-01 00:00:01 ~ 2037-12-31 23:59:59
155163

156164
关于两者的详细对比,请参考我写的[MySQL 时间类型数据存储建议](./some-thoughts-on-database-storage-time.md)
@@ -164,7 +172,11 @@ Timestamp 只需要使用 4 个字节的存储空间,但是 DateTime 需要耗
164172
- `NULL` 会影响聚合函数的结果。例如,`SUM``AVG``MIN``MAX` 等聚合函数会忽略 `NULL` 值。 `COUNT` 的处理方式取决于参数的类型。如果参数是 `*`(`COUNT(*)`),则会统计所有的记录数,包括 `NULL` 值;如果参数是某个字段名(`COUNT(列名)`),则会忽略 `NULL` 值,只统计非空值的个数。
165173
- 查询 `NULL` 值时,必须使用 `IS NULL``IS NOT NULLl` 来判断,而不能使用 =、!=、 <、> 之类的比较运算符。而`''`是可以使用这些比较运算符的。
166174

167-
看了上面的介绍之后,相信你对另外一个高频面试题:“为什么MySQL不建议使用 `NULL` 作为列默认值?”也有了答案。
175+
看了上面的介绍之后,相信你对另外一个高频面试题:“为什么 MySQL 不建议使用 `NULL` 作为列默认值?”也有了答案。
176+
177+
### Boolean 类型如何表示?
178+
179+
MySQL 中没有专门的布尔类型,而是用 TINYINT(1) 类型来表示布尔值。TINYINT(1) 类型可以存储 0 或 1,分别对应 false 或 true。
168180

169181
## MySQL 基础架构
170182

@@ -694,8 +706,8 @@ DELETE...
694706

695707
```sql
696708
CREATE TABLE `sequence_id` (
697-
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
698-
`stub` char(10) NOT NULL DEFAULT '',
709+
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
710+
`stub` CHAR(10) NOT NULL DEFAULT '',
699711
PRIMARY KEY (`id`),
700712
UNIQUE KEY `stub` (`stub`)
701713
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

0 commit comments

Comments
 (0)