mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-16 18:10:13 +08:00
commit
83f39a33b8
@ -21,7 +21,7 @@ tag:
|
||||
|
||||
### 所有表必须使用 InnoDB 存储引擎
|
||||
|
||||
没有特殊要求(即 InnoDB 无法满足的功能如:列存储,存储空间数据等)的情况下,所有表必须使用 InnoDB 存储引擎(MySQL5.5 之前默认使用 Myisam,5.6 以后默认的为 InnoDB)。
|
||||
没有特殊要求(即 InnoDB 无法满足的功能如:列存储,存储空间数据等)的情况下,所有表必须使用 InnoDB 存储引擎(MySQL5.5 之前默认使用 MyISAM,5.6 以后默认的为 InnoDB)。
|
||||
|
||||
InnoDB 支持事务,支持行级锁,更好的恢复性,高并发下性能更好。
|
||||
|
||||
|
@ -15,20 +15,20 @@ tag:
|
||||
|
||||
**索引是一种用于快速查询和检索数据的数据结构,其本质可以看成是一种排序好的数据结构。**
|
||||
|
||||
索引的作用就相当于书的目录。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
|
||||
索引的作用就相当于书的目录。打个比方:我们在查字典的时候,如果没有目录,那我们就只能一页一页地去找我们需要查的那个字,速度很慢;如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
|
||||
|
||||
索引底层数据结构存在很多种类型,常见的索引结构有: B 树, B+树 和 Hash、红黑树。在 MySQL 中,无论是 Innodb 还是 MyIsam,都使用了 B+树作为索引结构。
|
||||
索引底层数据结构存在很多种类型,常见的索引结构有:B 树、 B+ 树 和 Hash、红黑树。在 MySQL 中,无论是 Innodb 还是 MyISAM,都使用了 B+ 树作为索引结构。
|
||||
|
||||
## 索引的优缺点
|
||||
|
||||
**优点**:
|
||||
**优点:**
|
||||
|
||||
- 使用索引可以大大加快数据的检索速度(大大减少检索的数据量), 减少 IO 次数,这也是创建索引的最主要的原因。
|
||||
- 使用索引可以大大加快数据的检索速度(大大减少检索的数据量),减少 IO 次数,这也是创建索引的最主要的原因。
|
||||
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
|
||||
|
||||
**缺点**:
|
||||
**缺点:**
|
||||
|
||||
- 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
|
||||
- 创建和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态地修改,这会降低 SQL 执行效率。
|
||||
- 索引需要使用物理文件存储,也会耗费一定空间。
|
||||
|
||||
但是,**使用索引一定能提高查询性能吗?**
|
||||
@ -39,7 +39,7 @@ tag:
|
||||
|
||||
### Hash 表
|
||||
|
||||
哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。
|
||||
哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。
|
||||
|
||||
**为何能够通过 key 快速取出 value 呢?** 原因在于 **哈希算法**(也叫散列算法)。通过哈希算法,我们可以快速找到 key 对应的 index,找到了 index 也就找到了对应的 value。
|
||||
|
||||
@ -50,7 +50,7 @@ index = hash % array_size
|
||||
|
||||

|
||||
|
||||
但是!哈希算法有个 **Hash 冲突** 问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 **链地址法**。链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 `HashMap` 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后`HashMap`为了减少链表过长的时候搜索时间过长引入了红黑树。
|
||||
但是!哈希算法有个 **Hash 冲突** 问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 **链地址法**。链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 `HashMap` 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后`HashMap`为了提高链表过长时的搜索效率,引入了红黑树。
|
||||
|
||||

|
||||
|
||||
@ -60,15 +60,15 @@ MySQL 的 InnoDB 存储引擎不直接支持常规的哈希索引,但是,Inn
|
||||
|
||||
既然哈希表这么快,**为什么 MySQL 没有使用其作为索引的数据结构呢?** 主要是因为 Hash 索引不支持顺序和范围查询。假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了。并且,每次 IO 只能取一个。
|
||||
|
||||
试想一种情况:
|
||||
试想一种情况:
|
||||
|
||||
```java
|
||||
SELECT * FROM tb1 WHERE id < 500;
|
||||
```
|
||||
|
||||
在这种范围查询中,优势非常大,直接遍历比 500 小的叶子节点就够了。而 Hash 索引是根据 hash 算法来定位的,难不成还要把 1 - 499 的数据,每个都进行一次 hash 计算来定位吗?这就是 Hash 最大的缺点了。
|
||||
在这种范围查询中,优势非常大,直接遍历比 500 小的叶子节点就够了。而 Hash 索引是根据 hash 算法来定位的,难不成还要把 1 - 499 的数据,每个都进行一次 hash 计算来定位吗?这就是 Hash 最大的缺点了。
|
||||
|
||||
### 二叉查找树(BST)
|
||||
### 二叉查找树(BST)
|
||||
|
||||
二叉查找树(Binary Search Tree)是一种基于二叉树的数据结构,它具有以下特点:
|
||||
|
||||
@ -76,7 +76,7 @@ SELECT * FROM tb1 WHERE id < 500;
|
||||
2. 右子树所有节点的值均大于根节点的值。
|
||||
3. 左右子树也分别为二叉查找树。
|
||||
|
||||
当二叉查找树是平衡的时候,也就是树的每个节点的左右子树深度相差不超过 1 的时候,查询的时间复杂度为 O(log2(N)),具有比较高的效率。然而,当二叉查找树不平衡时,例如在最坏情况下(有序插入节点),树会退化成线性链表(也被称为斜树),导致查询效率急剧下降,时间复杂退化为 O(N)。
|
||||
当二叉查找树是平衡的时候,也就是树的每个节点的左右子树深度相差不超过 1 的时候,查询的时间复杂度为 O(log2(N)),具有比较高的效率。然而,当二叉查找树不平衡时,例如在最坏情况下(有序插入节点),树会退化成线性链表(也被称为斜树),导致查询效率急剧下降,时间复杂退化为 O(N)。
|
||||
|
||||

|
||||
|
||||
@ -114,14 +114,14 @@ AVL 树采用了旋转操作来保持平衡。主要有四种旋转操作:LL
|
||||
|
||||
### B 树& B+ 树
|
||||
|
||||
B 树也称 B-树,全称为 **多路平衡查找树** ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 `Balanced` (平衡)的意思。
|
||||
B 树也称 B- 树,全称为 **多路平衡查找树**,B+ 树是 B 树的一种变体。B 树和 B+ 树中的 B 是 `Balanced`(平衡)的意思。
|
||||
|
||||
目前大部分数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。
|
||||
|
||||
**B 树& B+ 树两者有何异同呢?**
|
||||
|
||||
- B 树的所有节点既存放键(key)也存放数据(data),而 B+ 树只有叶子节点存放 key 和 data,其他内节点只存放 key。
|
||||
- B 树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
|
||||
- B 树的叶子节点都是独立的;B+ 树的叶子节点有一条引用链指向与它相邻的叶子节点。
|
||||
- B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+ 树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。
|
||||
- 在 B 树中进行范围查询时,首先找到要查找的下限,然后对 B 树进行中序遍历,直到找到查找的上限;而 B+ 树的范围查询,只需要对链表进行遍历即可。
|
||||
|
||||
@ -140,12 +140,12 @@ B 树也称 B-树,全称为 **多路平衡查找树** ,B+ 树是 B 树的一
|
||||
- BTree 索引:MySQL 里默认和最常用的索引类型。只有叶子节点存储 value,非叶子节点只有指针和 key。存储引擎 MyISAM 和 InnoDB 实现 BTree 索引都是使用 B+Tree,但二者实现方式不一样(前面已经介绍了)。
|
||||
- 哈希索引:类似键值对的形式,一次即可定位。
|
||||
- RTree 索引:一般不会使用,仅支持 geometry 数据类型,优势在于范围查找,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
|
||||
- 全文索引:对文本的内容进行分词,进行搜索。目前只有 `CHAR`、`VARCHAR` ,`TEXT` 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
|
||||
- 全文索引:对文本的内容进行分词,进行搜索。目前只有 `CHAR`、`VARCHAR`、`TEXT` 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
|
||||
|
||||
按照底层存储方式角度划分:
|
||||
|
||||
- 聚簇索引(聚集索引):索引结构和数据一起存放的索引,InnoDB 中的主键索引就属于聚簇索引。
|
||||
- 非聚簇索引(非聚集索引):索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
|
||||
- 非聚簇索引(非聚集索引):索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
|
||||
|
||||
按照应用维度划分:
|
||||
|
||||
@ -154,7 +154,7 @@ B 树也称 B-树,全称为 **多路平衡查找树** ,B+ 树是 B 树的一
|
||||
- 唯一索引:加速查询 + 列值唯一(可以有 NULL)。
|
||||
- 覆盖索引:一个索引包含(或者说覆盖)所有需要查询的字段的值。
|
||||
- 联合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。
|
||||
- 全文索引:对文本的内容进行分词,进行搜索。目前只有 `CHAR`、`VARCHAR` ,`TEXT` 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
|
||||
- 全文索引:对文本的内容进行分词,进行搜索。目前只有 `CHAR`、`VARCHAR`、`TEXT` 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
|
||||
- 前缀索引:对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
|
||||
|
||||
MySQL 8.x 中实现的索引新特性:
|
||||
@ -163,7 +163,7 @@ MySQL 8.x 中实现的索引新特性:
|
||||
- 降序索引:之前的版本就支持通过 desc 来指定索引为降序,但实际上创建的仍然是常规的升序索引。直到 MySQL 8.x 版本才开始真正支持降序索引。另外,在 MySQL 8.x 版本中,不再对 GROUP BY 语句进行隐式排序。
|
||||
- 函数索引:从 MySQL 8.0.13 版本开始支持在索引中使用函数或者表达式的值,也就是在索引中可以包含函数或者表达式。
|
||||
|
||||
## 主键索引(Primary Key)
|
||||
## 主键索引(Primary Key)
|
||||
|
||||
数据表的主键列使用的就是主键索引。
|
||||
|
||||
@ -177,16 +177,16 @@ MySQL 8.x 中实现的索引新特性:
|
||||
|
||||
二级索引(Secondary Index)的叶子节点存储的数据是主键的值,也就是说,通过二级索引可以定位主键的位置,二级索引又称为辅助索引/非主键索引。
|
||||
|
||||
唯一索引,普通索引,前缀索引等索引都属于二级索引。
|
||||
唯一索引、普通索引、前缀索引等索引都属于二级索引。
|
||||
|
||||
PS: 不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,也可以自行搜索。
|
||||
PS:不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,也可以自行搜索。
|
||||
|
||||
1. **唯一索引(Unique Key)**:唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
|
||||
2. **普通索引(Index)**:普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
|
||||
3. **前缀索引(Prefix)**:前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
|
||||
4. **全文索引(Full Text)**:全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MYISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。
|
||||
1. **唯一索引(Unique Key):** 唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
|
||||
2. **普通索引(Index):** 普通索引的唯一作用就是为了快速查询数据。一张表允许创建多个普通索引,并允许数据重复和 NULL。
|
||||
3. **前缀索引(Prefix):** 前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
|
||||
4. **全文索引(Full Text):** 全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MyISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。
|
||||
|
||||
二级索引:
|
||||
二级索引:
|
||||
|
||||

|
||||
|
||||
@ -198,48 +198,48 @@ PS: 不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
|
||||
|
||||
聚簇索引(Clustered Index)即索引结构和数据一起存放的索引,并不是一种单独的索引类型。InnoDB 中的主键索引就属于聚簇索引。
|
||||
|
||||
在 MySQL 中,InnoDB 引擎的表的 `.ibd`文件就包含了该表的索引和数据,对于 InnoDB 引擎表来说,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。
|
||||
在 MySQL 中,InnoDB 引擎的表的 `.ibd`文件就包含了该表的索引和数据,对于 InnoDB 引擎表来说,该表的索引(B+ 树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。
|
||||
|
||||
#### 聚簇索引的优缺点
|
||||
|
||||
**优点**:
|
||||
**优点:**
|
||||
|
||||
- **查询速度非常快**:聚簇索引的查询速度非常的快,因为整个 B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引, 聚簇索引少了一次读取数据的 IO 操作。
|
||||
- **对排序查找和范围查找优化**:聚簇索引对于主键的排序查找和范围查找速度非常快。
|
||||
- **查询速度非常快:** 聚簇索引的查询速度非常的快,因为整个 B+ 树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引, 聚簇索引少了一次读取数据的 IO 操作。
|
||||
- **对排序查找和范围查找优化:** 聚簇索引对于主键的排序查找和范围查找速度非常快。
|
||||
|
||||
**缺点**:
|
||||
**缺点:**
|
||||
|
||||
- **依赖于有序的数据**:因为 B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
|
||||
- **更新代价大**:如果对索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。
|
||||
- **依赖于有序的数据:** 因为 B+ 树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
|
||||
- **更新代价大:** 如果对索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。
|
||||
|
||||
### 非聚簇索引(非聚集索引)
|
||||
|
||||
#### 非聚簇索引介绍
|
||||
|
||||
非聚簇索引(Non-Clustered Index)即索引结构和数据分开存放的索引,并不是一种单独的索引类型。二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
|
||||
非聚簇索引(Non-Clustered Index)即索引结构和数据分开存放的索引,并不是一种单独的索引类型。二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
|
||||
|
||||
非聚簇索引的叶子节点并不一定存放数据的指针,因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。
|
||||
|
||||
#### 非聚簇索引的优缺点
|
||||
|
||||
**优点**:
|
||||
**优点:**
|
||||
|
||||
更新代价比聚簇索引要小。非聚簇索引的更新代价就没有聚簇索引那么大了,非聚簇索引的叶子节点是不存放数据的。
|
||||
|
||||
**缺点**:
|
||||
**缺点:**
|
||||
|
||||
- **依赖于有序的数据**:跟聚簇索引一样,非聚簇索引也依赖于有序的数据
|
||||
- **可能会二次查询(回表)**:这应该是非聚簇索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。
|
||||
- **依赖于有序的数据:** 跟聚簇索引一样,非聚簇索引也依赖于有序的数据。
|
||||
- **可能会二次查询(回表):** 这应该是非聚簇索引最大的缺点了。当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。
|
||||
|
||||
这是 MySQL 的表的文件截图:
|
||||
这是 MySQL 的表的文件截图:
|
||||
|
||||

|
||||
|
||||
聚簇索引和非聚簇索引:
|
||||
聚簇索引和非聚簇索引:
|
||||
|
||||

|
||||
|
||||
#### 非聚簇索引一定回表查询吗(覆盖索引)?
|
||||
#### 非聚簇索引一定回表查询吗(覆盖索引)?
|
||||
|
||||
**非聚簇索引不一定回表查询。**
|
||||
|
||||
@ -251,7 +251,7 @@ PS: 不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
|
||||
|
||||
那么这个索引的 key 本身就是 name,查到对应的 name 直接返回就行了,无需回表查询。
|
||||
|
||||
即使是 MYISAM 也是这样,虽然 MYISAM 的主键索引确实需要回表,因为它的主键索引的叶子节点存放的是指针。但是!**如果 SQL 查的就是主键呢?**
|
||||
即使是 MyISAM 也是这样,虽然 MyISAM 的主键索引确实需要回表,因为它的主键索引的叶子节点存放的是指针。但是!**如果 SQL 查的就是主键呢?**
|
||||
|
||||
```sql
|
||||
SELECT id FROM table WHERE id=1;
|
||||
@ -400,7 +400,7 @@ MySQL 8.0.13 版本引入了索引跳跃扫描(Index Skip Scan,简称 ISS)
|
||||
|
||||
**索引下推(Index Condition Pushdown,简称 ICP)** 是 **MySQL 5.6** 版本中提供的一项索引优化功能,它允许存储引擎在索引遍历过程中,执行部分 `WHERE` 字句的判断条件,直接过滤掉不满足条件的记录,从而减少回表次数,提高查询效率。
|
||||
|
||||
假设我们有一个名为 `user` 的表,其中包含 `id`, `username`, `zipcode`和 `birthdate` 4 个字段,创建了联合索引`(zipcode, birthdate)`。
|
||||
假设我们有一个名为 `user` 的表,其中包含 `id`、`username`、`zipcode` 和 `birthdate` 4 个字段,创建了联合索引 `(zipcode, birthdate)`。
|
||||
|
||||
```sql
|
||||
CREATE TABLE `user` (
|
||||
@ -449,7 +449,7 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
||||
最后,总结一下索引下推应用范围:
|
||||
|
||||
1. 适用于 InnoDB 引擎和 MyISAM 引擎的查询。
|
||||
2. 适用于执行计划是 range, ref, eq_ref, ref_or_null 的范围查询。
|
||||
2. 适用于执行计划是 range、ref、eq_ref、ref_or_null 的范围查询。
|
||||
3. 对于 InnoDB 表,仅用于非聚簇索引。索引下推的目标是减少全行读取次数,从而减少 I/O 操作。对于 InnoDB 聚集索引,完整的记录已经读入 InnoDB 缓冲区。在这种情况下使用索引下推不会减少 I/O。
|
||||
4. 子查询不能使用索引下推,因为子查询通常会创建临时表来处理结果,而这些临时表是没有索引的。
|
||||
5. 存储过程不能使用索引下推,因为存储引擎无法调用存储函数。
|
||||
@ -458,11 +458,11 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
||||
|
||||
### 选择合适的字段创建索引
|
||||
|
||||
- **不为 NULL 的字段**:索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。
|
||||
- **被频繁查询的字段**:我们创建索引的字段应该是查询操作非常频繁的字段。
|
||||
- **被作为条件查询的字段**:被作为 WHERE 条件查询的字段,应该被考虑建立索引。
|
||||
- **频繁需要排序的字段**:索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
|
||||
- **被经常频繁用于连接的字段**:经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
|
||||
- **不为 NULL 的字段:** 索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0、1、true、false 这样语义较为清晰的短值或短字符作为替代。
|
||||
- **被频繁查询的字段:** 我们创建索引的字段应该是查询操作非常频繁的字段。
|
||||
- **被作为条件查询的字段:** 被作为 WHERE 条件查询的字段,应该被考虑建立索引。
|
||||
- **频繁需要排序的字段:** 索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
|
||||
- **被经常频繁用于连接的字段:** 经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
|
||||
|
||||
### 被频繁更新的字段应该慎重建立索引
|
||||
|
||||
@ -470,7 +470,7 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
||||
|
||||
### 限制每张表上的索引数量
|
||||
|
||||
索引并不是越多越好,建议单张表索引不超过 5 个!索引可以提高效率同样可以降低效率。
|
||||
索引并不是越多越好,建议单张表索引不超过 5 个!索引可以提高效率,同样可以降低效率。
|
||||
|
||||
索引可以增加查询效率,但同样也会降低插入和更新的效率,甚至有些情况下会降低查询效率。
|
||||
|
||||
@ -482,7 +482,7 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
||||
|
||||
### 注意避免冗余索引
|
||||
|
||||
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
|
||||
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city)和(name)这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的。在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
|
||||
|
||||
### 字符串类型的字段使用前缀索引代替普通索引
|
||||
|
||||
@ -492,13 +492,13 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
||||
|
||||
索引失效也是慢查询的主要原因之一,常见的导致索引失效的情况有下面这些:
|
||||
|
||||
- ~~使用 `SELECT *` 进行查询;~~ `SELECT *` 不会直接导致索引失效(如果不走索引大概率是因为 where 查询范围过大导致的),但它可能会带来一些其他的性能问题比如造成网络传输和数据处理的浪费、无法使用索引覆盖;
|
||||
- 创建了组合索引,但查询条件未遵守最左匹配原则;
|
||||
- 在索引列上进行计算、函数、类型转换等操作;
|
||||
- 以 % 开头的 LIKE 查询比如 `LIKE '%abc';`;
|
||||
- 查询条件中使用 OR,且 OR 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
|
||||
- IN 的取值范围较大时会导致索引失效,走全表扫描(NOT IN 和 IN 的失效场景相同);
|
||||
- 发生[隐式转换](https://javaguide.cn/database/mysql/index-invalidation-caused-by-implicit-conversion.html);
|
||||
- ~~使用 `SELECT *` 进行查询;~~ `SELECT *` 不会直接导致索引失效(如果不走索引大概率是因为 where 查询范围过大导致的),但它可能会带来一些其他的性能问题比如造成网络传输和数据处理的浪费、无法使用索引覆盖;
|
||||
- 创建了组合索引,但查询条件未遵守最左匹配原则;
|
||||
- 在索引列上进行计算、函数、类型转换等操作;
|
||||
- 以 % 开头的 LIKE 查询比如 `LIKE '%abc';`;
|
||||
- 查询条件中使用 OR,且 OR 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
|
||||
- IN 的取值范围较大时会导致索引失效,走全表扫描(NOT IN 和 IN 的失效场景相同);
|
||||
- 发生[隐式转换](https://javaguide.cn/database/mysql/index-invalidation-caused-by-implicit-conversion.html);
|
||||
- ……
|
||||
|
||||
推荐阅读这篇文章:[美团暑期实习一面:MySQl 索引失效的场景有哪些?](https://mp.weixin.qq.com/s/mwME3qukHBFul57WQLkOYg)。
|
||||
|
Loading…
x
Reference in New Issue
Block a user