auto commit
This commit is contained in:
parent
94274b2141
commit
85768bdf25
|
@ -9,7 +9,7 @@
|
|||
* [字符串](#字符串)
|
||||
* [时间和日期](#时间和日期)
|
||||
* [三、索引](#三索引)
|
||||
* [B-Tree 和 B+Tree 原理](#b-tree-和-btree-原理)
|
||||
* [B Tree 原理](#b-tree-原理)
|
||||
* [索引分类](#索引分类)
|
||||
* [索引的优点](#索引的优点)
|
||||
* [索引优化](#索引优化)
|
||||
|
@ -119,17 +119,17 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
# 三、索引
|
||||
|
||||
索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
|
||||
|
||||
索引能够轻易将查询性能提升几个数量级。
|
||||
|
||||
对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和使用索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。
|
||||
对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。
|
||||
|
||||
## B-Tree 和 B+Tree 原理
|
||||
索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
|
||||
|
||||
## B Tree 原理
|
||||
|
||||
### 1. B-Tree
|
||||
|
||||
<div align="center"> <img src="../pics//5ed71283-a070-4b21-85ae-f2cbfd6ba6e1.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//06976908-98ab-46e9-a632-f0c2760ec46c.png"/> </div><br>
|
||||
|
||||
定义一条数据记录为一个二元组 [key, data],B-Tree 是满足下列条件的数据结构:
|
||||
|
||||
|
@ -143,7 +143,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
### 2. B+Tree
|
||||
|
||||
<div align="center"> <img src="../pics//63cd5b50-d6d8-4df6-8912-ef4a1dd5ba13.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//7299afd2-9114-44e6-9d5e-4025d0b2a541.png"/> </div><br>
|
||||
|
||||
与 B-Tree 相比,B+Tree 有以下不同点:
|
||||
|
||||
|
@ -153,7 +153,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
### 3. 顺序访问指针
|
||||
|
||||
<div align="center"> <img src="../pics//1ee5f0a5-b8df-43b9-95ab-c516c54ec797.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//061c88c1-572f-424f-b580-9cbce903a3fe.png"/> </div><br>
|
||||
|
||||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 基础上进行了优化,在叶子节点增加了顺序访问指针,做这个优化的目的是为了提高区间访问的性能。
|
||||
|
||||
|
@ -161,7 +161,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
红黑树等平衡树也可以用来实现索引,但是文件系统及数据库系统普遍采用 B+Tree 和 B-Tree 作为索引结构,主要有以下两个原因:
|
||||
|
||||
**(一)更少的检索次数**
|
||||
(一)更少的检索次数
|
||||
|
||||
平衡树检索数据的时间复杂度等于树高 h,而树高大致为 O(h)=O(log<sub>d</sub>N),其中 d 为每个节点的出度。
|
||||
|
||||
|
@ -169,7 +169,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
B+Tree 相比于 B-Tree 更适合外存索引,因为 B+Tree 内节点去掉了 data 域,因此可以拥有更大的出度,检索效率会更高。
|
||||
|
||||
**(二)利用计算机预读特性**
|
||||
(二)利用计算机预读特性
|
||||
|
||||
为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道,并且只需要很短的旋转时间,因此速度会非常快。
|
||||
|
||||
|
@ -181,45 +181,50 @@ B+Tree 相比于 B-Tree 更适合外存索引,因为 B+Tree 内节点去掉了
|
|||
|
||||
### 1. B+Tree 索引
|
||||
|
||||
<div align="center"> <img src="../pics//c23957e9-a572-44f8-be15-f306c8b92722.jpg"/> </div><br>
|
||||
|
||||
《高性能 MySQL》一书使用 B-Tree 进行描述,其实从技术上来说这种索引是 B+Tree,因为只有叶子节点存储数据值。
|
||||
|
||||
B+Tree 索引是大多数 MySQL 存储引擎的默认索引类型。
|
||||
|
||||
因为不再需要进行全表扫描,只需要对树进行搜索即可,因此查找速度快很多。除了用于查找,还可以用于排序和分组。
|
||||
|
||||
可以指定多个列作为索引列,多个索引列共同组成键。B+Tree 索引适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。如果不是按照索引列的顺序进行查找,则无法使用索引。
|
||||
|
||||
InnoDB 的 B+Tree 索引分为主索引和辅助索引。
|
||||
|
||||
主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
|
||||
|
||||
<div align="center"> <img src="../pics//c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg"/> </div><br>
|
||||
|
||||
辅助索引的叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到主索引中进行查找。
|
||||
|
||||
<div align="center"> <img src="../pics//7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg"/> </div><br>
|
||||
|
||||
|
||||
|
||||
|
||||
### 2. 哈希索引
|
||||
|
||||
基于哈希表实现,优点是查找非常快。
|
||||
|
||||
在 MySQL 中只有 Memory 引擎显式支持哈希索引。
|
||||
|
||||
InnoDB 引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。
|
||||
|
||||
限制:
|
||||
哈希索引能以 O(1) 时间进行查找,但是失去了有序性,它具有以下限制:
|
||||
|
||||
- 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能影响并不明显;
|
||||
- 无法用于排序与分组;
|
||||
- 只支持精确查找,无法用于部分查找和范围查找;
|
||||
- 如果哈希冲突很多,查找速度会变得很慢。
|
||||
- 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能影响并不明显;
|
||||
|
||||
### 3. 空间数据索引(R-Tree)
|
||||
|
||||
MyISAM 存储引擎支持空间数据索引,可以用于地理数据存储。
|
||||
|
||||
空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。
|
||||
|
||||
必须使用 GIS 相关的函数来维护数据。
|
||||
|
||||
### 4. 全文索引
|
||||
### 3. 全文索引
|
||||
|
||||
MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较是否相等。查找条件使用 MATCH AGAINST,而不是普通的 WHERE。
|
||||
|
||||
全文索引一般使用倒排索引实现,它记录着关键词到其所在文档的映射。
|
||||
|
||||
InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引。
|
||||
|
||||
### 4. 空间数据索引(R-Tree)
|
||||
|
||||
MyISAM 存储引擎支持空间数据索引,可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。
|
||||
|
||||
必须使用 GIS 相关的函数来维护数据。
|
||||
|
||||
## 索引的优点
|
||||
|
||||
- 大大减少了服务器需要扫描的数据行数。
|
||||
|
@ -278,35 +283,12 @@ customer_id_selectivity: 0.0373
|
|||
|
||||
索引包含所有需要查询的字段的值。
|
||||
|
||||
**优点**
|
||||
具有以下优点优点:
|
||||
|
||||
- 因为索引条目通常远小于数据行的大小,所以若只读取索引,能大大减少数据访问量。
|
||||
- 一些存储引擎(例如 MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。
|
||||
- 对于 InnoDB 引擎,若二级索引能够覆盖查询,则无需访问聚簇索引。
|
||||
|
||||
### 6. 聚簇索引
|
||||
|
||||
<div align="center"> <img src="../pics//e800b001-7779-495b-8459-d33a7440d7b8.jpg"/> </div><br>
|
||||
|
||||
聚簇索引并不是一种索引类型,而是一种数据存储方式。
|
||||
|
||||
术语“聚簇”表示数据行和相邻的键值紧密地存储在一起,InnoDB 的聚簇索引在同一个结构中保存了 B+Tree 索引和数据行。
|
||||
|
||||
因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
|
||||
|
||||
**优点**
|
||||
|
||||
- 可以把相关数据保存在一起,减少 I/O 操作。例如电子邮件表可以根据用户 ID 来聚集数据,这样只需要从磁盘读取少数的数据也就能获取某个用户的全部邮件,如果没有使用聚簇索引,则每封邮件都可能导致一次磁盘 I/O。
|
||||
- 数据访问更快。
|
||||
|
||||
**缺点**
|
||||
|
||||
- 聚簇索引最大限度提高了 I/O 密集型应用的性能,但是如果数据全部放在内存,就没必要用聚簇索引。
|
||||
- 插入速度严重依赖于插入顺序,按主键的顺序插入是最快的。
|
||||
- 更新操作代价很高,因为每个被更新的行都会移动到新的位置。
|
||||
- 当插入到某个已满的页中,存储引擎会将该页分裂成两个页面来容纳该行,页分裂会导致表占用更多的磁盘空间。
|
||||
- 如果行比较稀疏,或者由于页分裂导致数据存储不连续时,聚簇索引可能导致全表扫描速度变慢。
|
||||
|
||||
# 四、查询性能优化
|
||||
|
||||
## 使用 Explain 进行分析
|
||||
|
@ -325,15 +307,15 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai
|
|||
|
||||
### 1. 减少请求的数据量
|
||||
|
||||
**(一)只返回必要的列**
|
||||
(一)只返回必要的列
|
||||
|
||||
最好不要使用 SELECT * 语句。
|
||||
|
||||
**(二)只返回必要的行**
|
||||
(二)只返回必要的行
|
||||
|
||||
使用 WHERE 语句进行查询过滤,有时候也需要使用 LIMIT 语句来限制返回的数据。
|
||||
|
||||
**(三)缓存重复查询的数据**
|
||||
(三)缓存重复查询的数据
|
||||
|
||||
使用缓存可以避免在数据库中进行查询,特别要查询的数据经常被重复查询,缓存可以带来的查询性能提升将会是非常明显的。
|
||||
|
||||
|
@ -456,6 +438,7 @@ MySQL 读写分离能提高性能的原因在于:
|
|||
# 参考资料
|
||||
|
||||
- BaronScbwartz, PeterZaitsev, VadimTkacbenko, 等. 高性能 MySQL[M]. 电子工业出版社, 2013.
|
||||
- 姜承尧. MySQL 技术内幕: InnoDB 存储引擎 [M]. 机械工业出版社, 2011.
|
||||
- [20+ 条 MySQL 性能优化的最佳经验](https://www.jfox.info/20-tiao-mysql-xing-nen-you-hua-de-zui-jia-jing-yan.html)
|
||||
- [服务端指南 数据存储篇 | MySQL(09) 分库与分表带来的分布式困境与应对之策](http://blog.720ui.com/2017/mysql_core_09_multi_db_table2/ "服务端指南 数据存储篇 | MySQL(09) 分库与分表带来的分布式困境与应对之策")
|
||||
- [How to create unique row ID in sharded databases?](https://stackoverflow.com/questions/788829/how-to-create-unique-row-id-in-sharded-databases)
|
||||
|
|
BIN
pics/061c88c1-572f-424f-b580-9cbce903a3fe.png
Normal file
BIN
pics/061c88c1-572f-424f-b580-9cbce903a3fe.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
pics/06976908-98ab-46e9-a632-f0c2760ec46c.png
Normal file
BIN
pics/06976908-98ab-46e9-a632-f0c2760ec46c.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
BIN
pics/7299afd2-9114-44e6-9d5e-4025d0b2a541.png
Normal file
BIN
pics/7299afd2-9114-44e6-9d5e-4025d0b2a541.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
pics/7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg
Normal file
BIN
pics/7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
pics/c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg
Normal file
BIN
pics/c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
Loading…
Reference in New Issue
Block a user