Skip to content

Commit 97ae1ae

Browse files
authored
Merge pull request #2628 from YJRY/main
文档内容勘误
2 parents 83f39a3 + 86af2d5 commit 97ae1ae

4 files changed

+195
-195
lines changed

docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ tag:
2121

2222
### 所有表必须使用 InnoDB 存储引擎
2323

24-
没有特殊要求(即 InnoDB 无法满足的功能如:列存储存储空间数据等)的情况下,所有表必须使用 InnoDB 存储引擎(MySQL5.5 之前默认使用 MyISAM,5.6 以后默认的为 InnoDB)。
24+
没有特殊要求(即 InnoDB 无法满足的功能如:列存储存储空间数据等)的情况下,所有表必须使用 InnoDB 存储引擎(MySQL5.5 之前默认使用 MyISAM,5.6 以后默认的为 InnoDB)。
2525

2626
InnoDB 支持事务,支持行级锁,更好的恢复性,高并发下性能更好。
2727

@@ -198,9 +198,9 @@ InnoDB 是按照主键索引的顺序来组织表的。
198198

199199
建立索引的目的是:希望通过索引进行数据查找,减少随机 IO,增加查询性能,索引能过滤出越少的数据,则从磁盘中读入的数据也就越少。
200200

201-
- **区分度最高的列放在联合索引的最左侧** 这是最重要的原则。区分度越高,通过索引筛选出的数据就越少,I/O 操作也就越少。计算区分度的方法是 `count(distinct column) / count(*)`
202-
- **最频繁使用的列放在联合索引的左侧** 这符合最左前缀匹配原则。将最常用的查询条件列放在最左侧,可以最大程度地利用索引。
203-
- **字段长度** 字段长度对联合索引非叶子节点的影响很小,因为它存储了所有联合索引字段的值。字段长度主要影响主键和包含在其他索引中的字段的存储空间,以及这些索引的叶子节点的大小。因此,在选择联合索引列的顺序时,字段长度的优先级最低。对于主键和包含在其他索引中的字段,选择较短的字段长度可以节省存储空间和提高 I/O 性能。
201+
- **区分度最高的列放在联合索引的最左侧**这是最重要的原则。区分度越高,通过索引筛选出的数据就越少,I/O 操作也就越少。计算区分度的方法是 `count(distinct column) / count(*)`
202+
- **最频繁使用的列放在联合索引的左侧**这符合最左前缀匹配原则。将最常用的查询条件列放在最左侧,可以最大程度地利用索引。
203+
- **字段长度**字段长度对联合索引非叶子节点的影响很小,因为它存储了所有联合索引字段的值。字段长度主要影响主键和包含在其他索引中的字段的存储空间,以及这些索引的叶子节点的大小。因此,在选择联合索引列的顺序时,字段长度的优先级最低。对于主键和包含在其他索引中的字段,选择较短的字段长度可以节省存储空间和提高 I/O 性能。
204204

205205
### 避免建立冗余索引和重复索引(增加了查询优化器生成执行计划的时间)
206206

@@ -211,10 +211,10 @@ InnoDB 是按照主键索引的顺序来组织表的。
211211

212212
> 覆盖索引:就是包含了所有查询字段 (where、select、order by、group by 包含的字段) 的索引
213213
214-
**覆盖索引的好处**
214+
**覆盖索引的好处**
215215

216-
- **避免 InnoDB 表进行索引的二次查询,也就是回表操作** InnoDB 是以聚集索引的顺序来存储的,对于 InnoDB 来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询(回表),减少了 IO 操作,提升了查询效率。
217-
- **可以把随机 IO 变成顺序 IO 加快查询效率** 由于覆盖索引是按键值的顺序存储的,对于 IO 密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO 转变成索引查找的顺序 IO。
216+
- **避免 InnoDB 表进行索引的二次查询,也就是回表操作**InnoDB 是以聚集索引的顺序来存储的,对于 InnoDB 来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询(回表),减少了 IO 操作,提升了查询效率。
217+
- **可以把随机 IO 变成顺序 IO 加快查询效率**由于覆盖索引是按键值的顺序存储的,对于 IO 密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO 转变成索引查找的顺序 IO。
218218

219219
---
220220

@@ -253,13 +253,13 @@ InnoDB 是按照主键索引的顺序来组织表的。
253253

254254
### 禁止使用不含字段列表的 INSERT 语句
255255

256-
**不推荐**
256+
**不推荐**
257257

258258
```sql
259259
insert into t values ('a','b','c');
260260
```
261261

262-
**推荐**
262+
**推荐**
263263

264264
```sql
265265
insert into t(c1,c2,c3) values ('a','b','c');
@@ -285,7 +285,7 @@ select name,phone from customer where id = '111';
285285

286286
通常子查询在 in 子句中,且子查询中为简单 SQL(不包含 union、group by、order by、limit 从句) 时,才可以把子查询转化为关联查询进行优化。
287287

288-
**子查询性能差的原因** 子查询的结果集无法使用索引,通常子查询的结果集会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引,所以查询性能会受到一定的影响。特别是对于返回结果集比较大的子查询,其对查询性能的影响也就越大。由于子查询会产生大量的临时表也没有索引,所以会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。
288+
**子查询性能差的原因**子查询的结果集无法使用索引,通常子查询的结果集会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引,所以查询性能会受到一定的影响。特别是对于返回结果集比较大的子查询,其对查询性能的影响也就越大。由于子查询会产生大量的临时表也没有索引,所以会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。
289289

290290
### 避免使用 JOIN 关联太多的表
291291

@@ -315,13 +315,13 @@ order by rand() 会把表中所有符合条件的数据装载到内存中,然
315315

316316
对列进行函数转换或计算时会导致无法使用索引。
317317

318-
**不推荐**
318+
**不推荐**
319319

320320
```sql
321321
where date(create_time)='20190101'
322322
```
323323

324-
**推荐**
324+
**推荐**
325325

326326
```sql
327327
where create_time >= '20190101' and create_time < '20190102'

docs/database/mysql/mysql-index.md

+22-22
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ tag:
2121

2222
## 索引的优缺点
2323

24-
**优点**
24+
**优点**
2525

2626
- 使用索引可以大大加快数据的检索速度(大大减少检索的数据量),减少 IO 次数,这也是创建索引的最主要的原因。
2727
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
2828

29-
**缺点**
29+
**缺点**
3030

3131
- 创建和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态地修改,这会降低 SQL 执行效率。
3232
- 索引需要使用物理文件存储,也会耗费一定空间。
@@ -181,10 +181,10 @@ MySQL 8.x 中实现的索引新特性:
181181

182182
PS:不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,也可以自行搜索。
183183

184-
1. **唯一索引(Unique Key)** 唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
185-
2. **普通索引(Index)** 普通索引的唯一作用就是为了快速查询数据。一张表允许创建多个普通索引,并允许数据重复和 NULL。
186-
3. **前缀索引(Prefix)** 前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
187-
4. **全文索引(Full Text)** 全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MyISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。
184+
1. **唯一索引(Unique Key)**唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
185+
2. **普通索引(Index)**普通索引的唯一作用就是为了快速查询数据。一张表允许创建多个普通索引,并允许数据重复和 NULL。
186+
3. **前缀索引(Prefix)**前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
187+
4. **全文索引(Full Text)**全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MyISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。
188188

189189
二级索引:
190190

@@ -202,15 +202,15 @@ PS:不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
202202

203203
#### 聚簇索引的优缺点
204204

205-
**优点**
205+
**优点**
206206

207-
- **查询速度非常快** 聚簇索引的查询速度非常的快,因为整个 B+ 树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引, 聚簇索引少了一次读取数据的 IO 操作。
208-
- **对排序查找和范围查找优化** 聚簇索引对于主键的排序查找和范围查找速度非常快。
207+
- **查询速度非常快**聚簇索引的查询速度非常的快,因为整个 B+ 树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引, 聚簇索引少了一次读取数据的 IO 操作。
208+
- **对排序查找和范围查找优化**聚簇索引对于主键的排序查找和范围查找速度非常快。
209209

210-
**缺点**
210+
**缺点**
211211

212-
- **依赖于有序的数据** 因为 B+ 树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
213-
- **更新代价大** 如果对索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。
212+
- **依赖于有序的数据**因为 B+ 树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
213+
- **更新代价大**如果对索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。
214214

215215
### 非聚簇索引(非聚集索引)
216216

@@ -222,14 +222,14 @@ PS:不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
222222

223223
#### 非聚簇索引的优缺点
224224

225-
**优点**
225+
**优点**
226226

227227
更新代价比聚簇索引要小。非聚簇索引的更新代价就没有聚簇索引那么大了,非聚簇索引的叶子节点是不存放数据的。
228228

229-
**缺点**
229+
**缺点**
230230

231-
- **依赖于有序的数据** 跟聚簇索引一样,非聚簇索引也依赖于有序的数据。
232-
- **可能会二次查询(回表)** 这应该是非聚簇索引最大的缺点了。当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。
231+
- **依赖于有序的数据**跟聚簇索引一样,非聚簇索引也依赖于有序的数据。
232+
- **可能会二次查询(回表)**这应该是非聚簇索引最大的缺点了。当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。
233233

234234
这是 MySQL 的表的文件截图:
235235

@@ -391,7 +391,7 @@ SELECT * FROM student WHERE class = 'lIrm08RYVk';
391391
先不要往下看答案,给自己 3 分钟时间想一想。
392392

393393
1. 查询 `a=1 AND c=1`:根据最左前缀匹配原则,查询可以使用索引的前缀部分。因此,该查询仅在 `a=1` 上使用索引,然后对结果进行 `c=1` 的过滤。
394-
2. 查询 `c=1` :由于查询中不包含最左列 `a`,根据最左前缀匹配原则,整个索引都无法被使用。
394+
2. 查询 `c=1`:由于查询中不包含最左列 `a`,根据最左前缀匹配原则,整个索引都无法被使用。
395395
3. 查询 `b=1 AND c=1`:和第二种一样的情况,整个索引都不会使用。
396396

397397
MySQL 8.0.13 版本引入了索引跳跃扫描(Index Skip Scan,简称 ISS),它可以在某些索引查询场景下提高查询效率。在没有 ISS 之前,不满足最左前缀匹配原则的联合索引查询中会执行全表扫描。而 ISS 允许 MySQL 在某些情况下避免全表扫描,即使查询条件不符合最左前缀。不过,这个功能比较鸡肋, 和 Oracle 中的没法比,MySQL 8.0.31 还报告了一个 bug:[Bug #109145 Using index for skip scan cause incorrect result](https://bugs.mysql.com/bug.php?id=109145)(后续版本已经修复)。个人建议知道有这个东西就好,不需要深究,实际项目也不一定能用上。
@@ -458,11 +458,11 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
458458

459459
### 选择合适的字段创建索引
460460

461-
- **不为 NULL 的字段** 索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0、1、true、false 这样语义较为清晰的短值或短字符作为替代。
462-
- **被频繁查询的字段** 我们创建索引的字段应该是查询操作非常频繁的字段。
463-
- **被作为条件查询的字段** 被作为 WHERE 条件查询的字段,应该被考虑建立索引。
464-
- **频繁需要排序的字段** 索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
465-
- **被经常频繁用于连接的字段** 经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
461+
- **不为 NULL 的字段**索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0、1、true、false 这样语义较为清晰的短值或短字符作为替代。
462+
- **被频繁查询的字段**我们创建索引的字段应该是查询操作非常频繁的字段。
463+
- **被作为条件查询的字段**被作为 WHERE 条件查询的字段,应该被考虑建立索引。
464+
- **频繁需要排序的字段**索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
465+
- **被经常频繁用于连接的字段**经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
466466

467467
### 被频繁更新的字段应该慎重建立索引
468468

0 commit comments

Comments
 (0)