auto commit

This commit is contained in:
CyC2018
2020-11-17 00:32:18 +08:00
parent f5ad47b470
commit 7e61fc1360
380 changed files with 2371 additions and 46715 deletions

View File

@ -1,40 +1,21 @@
# MySQL
<!-- GFM-TOC -->
* [索引](#一索引)
* [B+ Tree 原理](#b-tree-原理)
* [MySQL 索引](#mysql-索引)
* [索引优化](#索引优化)
* [索引的优点](#索引的优点)
* [索引的使用条件](#索引的使用条件)
* [查询性能优化](#二查询性能优化)
* [使用 Explain 进行分析](#使用-explain-进行分析)
* [优化数据访问](#优化数据访问)
* [重构查询方式](#重构查询方式)
* [存储引擎](#三存储引擎)
* [InnoDB](#innodb)
* [MyISAM](#myisam)
* [比较](#比较)
* [数据类型](#四数据类型)
* [整型](#整型)
* [浮点数](#浮点数)
* [字符串](#字符串)
* [时间和日期](#时间和日期)
* [切分](#五切分)
* [水平切分](#水平切分)
* [垂直切分](#垂直切分)
* [Sharding 策略](#sharding-策略)
* [Sharding 存在的问题](#sharding-存在的问题)
* [复制](#六复制)
* [主从复制](#主从复制)
* [读写分离](#读写分离)
* [参考资料](#参考资料)
* [MySQL](#mysql)
* [索引](#一索引)
* [查询性能优化](#二查询性能优化)
* [存储引擎](#三存储引擎)
* [数据类型](#四数据类型)
* [切分](#五切分)
* [复制](#六复制)
* [参考资料](#参考资料)
<!-- GFM-TOC -->
# 索引
## 索引
## B+ Tree 原理
### B+ Tree 原理
### 1. 数据结构
#### 1. 数据结构
B Tree 指的是 Balance Tree也就是平衡树平衡树是一颗查找树并且所有叶子节点位于同一层
@ -44,13 +25,13 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/33576849-9275-47bb-ada7-8ded5f5e7c73.png" width="350px"> </div><br>
### 2. 操作
#### 2. 操作
进行查找操作时首先在根节点进行二分查找找到一个 key 所在的指针然后递归地在指针所指向的节点进行查找直到查找到叶子节点然后在叶子节点上进行二分查找找出 key 所对应的 data
插入删除操作会破坏平衡树的平衡性因此在进行插入删除操作之后需要对树进行分裂合并旋转等操作来维护平衡性
### 3. 与红黑树的比较
#### 3. 与红黑树的比较
红黑树等平衡树也可以用来实现索引但是文件系统及数据库系统普遍采用 B+ Tree 作为索引结构这是因为使用 B+ 树访问磁盘数据有更高的性能
@ -68,11 +49,11 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
为了减少磁盘 I/O 操作磁盘往往不是严格按需读取而是每次都会预读预读过程中磁盘进行顺序读取顺序读取不需要进行磁盘寻道并且只需要很短的磁盘旋转时间速度会非常快并且可以利用预读特性相邻的节点也能够被预先载入
## MySQL 索引
### MySQL 索引
索引是在存储引擎层实现的而不是在服务器层实现的所以不同存储引擎具有不同的索引类型和实现
### 1. B+Tree 索引
#### 1. B+Tree 索引
是大多数 MySQL 存储引擎的默认索引类型
@ -92,7 +73,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7c349b91-050b-4d72-a7f8-ec86320307ea.png" width="350px"> </div><br>
### 2. 哈希索引
#### 2. 哈希索引
哈希索引能以 O(1) 时间进行查找但是失去了有序性
@ -101,7 +82,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节
InnoDB 存储引擎有一个特殊的功能叫自适应哈希索引当某个索引值被使用的非常频繁时会在 B+Tree 索引之上再创建一个哈希索引这样就让 B+Tree 索引具有哈希索引的一些优点比如快速的哈希查找
### 3. 全文索引
#### 3. 全文索引
MyISAM 存储引擎支持全文索引用于查找文本中的关键词而不是直接比较是否相等
@ -111,15 +92,15 @@ MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而
InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引
### 4. 空间数据索引
#### 4. 空间数据索引
MyISAM 存储引擎支持空间数据索引R-Tree可以用于地理数据存储空间数据索引会从所有维度来索引数据可以有效地使用任意维度来进行组合查询
必须使用 GIS 相关的函数来维护数据
## 索引优化
### 索引优化
### 1. 独立的列
#### 1. 独立的列
在进行查询时索引列不能是表达式的一部分也不能是函数的参数否则无法使用索引
@ -129,7 +110,7 @@ MyISAM 存储引擎支持空间数据索引R-Tree可以用于地理数
SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
```
### 2. 多列索引
#### 2. 多列索引
在需要使用多个列作为条件进行查询时使用多列索引比使用多个单列索引性能更好例如下面的语句中最好把 actor_id film_id 设置为多列索引
@ -138,7 +119,7 @@ SELECT film_id, actor_ id FROM sakila.film_actor
WHERE actor_id = 1 AND film_id = 1;
```
### 3. 索引列的顺序
#### 3. 索引列的顺序
让选择性最强的索引列放在前面
@ -159,13 +140,13 @@ customer_id_selectivity: 0.0373
COUNT(*): 16049
```
### 4. 前缀索引
#### 4. 前缀索引
对于 BLOBTEXT VARCHAR 类型的列必须使用前缀索引只索引开始的部分字符
前缀长度的选取需要根据索引选择性来确定
### 5. 覆盖索引
#### 5. 覆盖索引
索引包含所有需要查询的字段的值
@ -175,7 +156,7 @@ customer_id_selectivity: 0.0373
- 一些存储引擎例如 MyISAM在内存中只缓存索引而数据依赖于操作系统来缓存因此只访问索引可以不使用系统调用通常比较费时
- 对于 InnoDB 引擎若辅助索引能够覆盖查询则无需访问主索引
## 索引的优点
### 索引的优点
- 大大减少了服务器需要扫描的数据行数
@ -183,7 +164,7 @@ customer_id_selectivity: 0.0373
- 将随机 I/O 变为顺序 I/OB+Tree 索引是有序的会将相邻的数据都存储在一起
## 索引的使用条件
### 索引的使用条件
- 对于非常小的表大部分情况下简单的全表扫描比建立索引更高效
@ -191,9 +172,9 @@ customer_id_selectivity: 0.0373
- 但是对于特大型的表建立和维护索引的代价将会随之增长这种情况下需要用到一种技术可以直接区分出需要查询的一组数据而不是一条记录一条记录地匹配例如可以使用分区技术
# 查询性能优化
## 查询性能优化
## 使用 Explain 进行分析
### 使用 Explain 进行分析
Explain 用来分析 SELECT 查询语句开发人员可以通过分析 Explain 结果来优化查询语句
@ -203,21 +184,21 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai
- key : 使用的索引
- rows : 扫描的行数
## 优化数据访问
### 优化数据访问
### 1. 减少请求的数据量
#### 1. 减少请求的数据量
- 只返回必要的列最好不要使用 SELECT * 语句
- 只返回必要的行使用 LIMIT 语句来限制返回的数据
- 缓存重复查询的数据使用缓存可以避免在数据库中进行查询特别在要查询的数据经常被重复查询时缓存带来的查询性能提升将会是非常明显的
### 2. 减少服务器端扫描的行数
#### 2. 减少服务器端扫描的行数
最有效的方式是使用索引来覆盖查询
## 重构查询方式
### 重构查询方式
### 1. 切分大查询
#### 1. 切分大查询
一个大查询如果一次性执行的话可能一次锁住很多数据占满整个事务日志耗尽系统资源阻塞很多小的但重要的查询
@ -233,7 +214,7 @@ do {
} while rows_affected > 0
```
### 2. 分解大连接查询
#### 2. 分解大连接查询
将一个大连接查询分解成对每一个表进行一次单表查询然后在应用程序中进行关联这样做的好处有
@ -256,9 +237,9 @@ SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
```
# 存储引擎
## 存储引擎
## InnoDB
### InnoDB
MySQL 默认的事务型存储引擎只有在需要它不支持的特性时才考虑使用其它存储引擎
@ -270,7 +251,7 @@ SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
支持真正的在线热备份其它存储引擎不支持在线热备份要获取一致性视图需要停止对所有表的写入而在读写混合场景中停止写入可能也意味着停止读取
## MyISAM
### MyISAM
设计简单数据以紧密格式存储对于只读数据或者表比较小可以容忍修复操作则依然可以使用它
@ -284,7 +265,7 @@ SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
如果指定了 DELAY_KEY_WRITE 选项在每次修改执行完成时不会立即将修改的索引数据写入磁盘而是会写到内存中的键缓冲区只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘这种方式可以极大的提升写入性能但是在数据库或者主机崩溃时会造成索引损坏需要执行修复操作
## 比较
### 比较
- 事务InnoDB 是事务型的可以使用 Commit Rollback 语句
@ -298,21 +279,21 @@ SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
- 其它特性MyISAM 支持压缩表和空间数据索引
# 数据类型
## 数据类型
## 整型
### 整型
TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT 分别使用 8, 16, 24, 32, 64 位存储空间一般情况下越小的列越好
INT(11) 中的数字只是规定了交互工具显示字符的个数对于存储和计算来说是没有意义的
## 浮点数
### 浮点数
FLOAT DOUBLE 为浮点类型DECIMAL 为高精度小数类型CPU 原生支持浮点运算但是不支持 DECIMAl 类型的计算因此 DECIMAL 的计算比浮点类型需要更高的代价
FLOATDOUBLE DECIMAL 都可以指定列宽例如 DECIMAL(18, 9) 表示总共 18 9 位存储小数部分剩下 9 位存储整数部分
## 字符串
### 字符串
主要有 CHAR VARCHAR 两种类型一种是定长的一种是变长的
@ -320,19 +301,19 @@ VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内
在进行存储和检索时会保留 VARCHAR 末尾的空格而会删除 CHAR 末尾的空格
## 时间和日期
### 时间和日期
MySQL 提供了两种相似的日期时间类型DATETIME TIMESTAMP
### 1. DATETIME
#### 1. DATETIME
能够保存从 1000 年到 9999 年的日期和时间精度为秒使用 8 字节的存储空间
它与时区无关
默认情况下MySQL 以一种可排序的无歧义的格式显示 DATETIME 例如2008-01-16 22<span>:</span>37<span>:</span>08这是 ANSI 标准定义的日期和时间表示方法
默认情况下MySQL 以一种可排序的无歧义的格式显示 DATETIME 例如2008-01-16 22\<span\>:\</span\>37\<span\>:\</span\>08这是 ANSI 标准定义的日期和时间表示方法
### 2. TIMESTAMP
#### 2. TIMESTAMP
UNIX 时间戳相同保存从 1970 1 1 日午夜格林威治时间以来的秒数使用 4 个字节只能表示从 1970 年到 2038
@ -344,9 +325,9 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
应该尽量使用 TIMESTAMP因为它比 DATETIME 空间效率更高
# 切分
## 切分
## 水平切分
### 水平切分
水平切分又称为 Sharding它是将同一个表中的记录拆分到多个结构相同的表中
@ -354,7 +335,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg" width=""> </div><br>
## 垂直切分
### 垂直切分
垂直切分是将一张表按列切分成多个表通常是按照列的关系密集程度进行切分也可以利用垂直切分将经常被使用的列和不经常被使用的列切分到不同的表中
@ -362,31 +343,31 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg" width=""> </div><br>
## Sharding 策略
### Sharding 策略
- 哈希取模hash(key) % N
- 范围可以是 ID 范围也可以是时间范围
- 映射表使用单独的一个数据库来存储映射关系
## Sharding 存在的问题
### Sharding 存在的问题
### 1. 事务问题
#### 1. 事务问题
使用分布式事务来解决比如 XA 接口
### 2. 连接
#### 2. 连接
可以将原来的连接分解成多个单表查询然后在用户程序中进行连接
### 3. ID 唯一性
#### 3. ID 唯一性
- 使用全局唯一 IDGUID
- 为每个分片指定一个 ID 范围
- 分布式 ID 生成器 ( Twitter Snowflake 算法)
# 复制
## 复制
## 主从复制
### 主从复制
主要涉及三个线程binlog 线程I/O 线程和 SQL 线程
@ -396,7 +377,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/master-slave.png" width=""> </div><br>
## 读写分离
### 读写分离
主服务器处理写操作以及实时性要求比较高的读操作而从服务器处理读操作
@ -410,7 +391,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/master-slave-proxy.png" width=""> </div><br>
# 参考资料
## 参考资料
- BaronScbwartz, PeterZaitsev, VadimTkacbenko, . 高性能 MySQL[M]. 电子工业出版社, 2013.
- 姜承尧. MySQL 技术内幕: InnoDB 存储引擎 [M]. 机械工业出版社, 2011.
@ -423,10 +404,3 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
- [How Sharding Works](https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6)
- [大众点评订单系统分库分表实践](https://tech.meituan.com/dianping_order_db_sharding.html)
- [B + ](https://zh.wikipedia.org/wiki/B%2B%E6%A0%91)
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>