年轻人不讲武德,乱用索引,你到底走了多少弯路?

运维 数据库运维
今天我们一起索引使用相关原则进行了简单梳理,要记住:索引是能够提升SQL 查询的效率,但是索引不是万能的,一定要遵守基本原则。

[[409635]]

本文转载自微信公众号「码上Java」,作者码上Java。转载本文请联系码上Java公众号。

前言

上一篇文章中我们一起探讨了索引的底层原理及为什么我们常用B+树作为索引的数据结构。本文我们一起学习一下索引创建的原则,看看什么时候适合创建索引?看看什么时候不适合创建索引?

什么情况下适合创建索引

1. 字段的数值有唯一性的限制,比如用户名

索引本身可以起到约束的作用,比如唯一索引、主键索引都是可以起到唯一性约束的,因此在我们的数据表中,如果某个字段是唯一性的,就可以直接创建唯一性索引,或者主键索引。

2. 频繁作为 WHERE 查询条件的字段,尤其在数据表大的情况下

在数据量大的情况下,某个字段在 SQL 查询的 WHERE 条件中经常被使用到,那么就需要给这个字段创建索引了。创建普通索引就可以大幅提升数据查询的效率。

3. 需要经常 GROUP BY 和 ORDER BY 的列

索引就是让数据按照某种顺序进行存储或检索,因此当我们使用 GROUP BY 对数据进行分组查询,或者使用 ORDER BY 对数据进行排序的时候,就需要对分组或者排序的字段进行索引。

4.UPDATE、DELETE 的 WHERE 条件列,一般也需要创建索引

对数据按照某个条件进行查询后再进行 UPDATE 或 DELETE 的操作,如果对 WHERE 字段创建了索引,就能大幅提升效率。原理是因为我们需要先根据 WHERE 条件列检索出来这条记录,然后再对它进行更新或删除。如果进行更新的时候,更新的字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护。

不过在实际工作中,我们也需要注意平衡,如果索引太多了,在更新数据的时候,如果涉及到索引更新,就会造成负担。

5.DISTINCT 字段需要创建索引

有时候我们需要对某个字段进行去重,使用 DISTINCT,那么对这个字段创建索引,也会提升查询效率。

6. 做多表 JOIN 连接操作时,创建索引需要注意以下的原则

连接表的数量尽量不要超过 3 张,因为每增加一张表就相当于增加了一次嵌套的循环,数量级增长会非常快,严重影响查询的效率。

对 WHERE 条件创建索引,因为 WHERE 才是对数据条件的过滤。如果在数据量非常大的情况下,没有 WHERE 条件过滤是非常可怕的。

对用于连接的字段创建索引,并且该字段在多张表中的类型必须一致。

什么情况适合创建索引

1. 频繁更新的字段不适合建立索引。

这个是为什么呢?你要知道,索引为什么能够提高查询效率呢,那是因为索引在插入数据的时候会对数据进行排序。所以说,如果涉及频繁更新的字段的话,这个时候就不适合建立索引了。

这里以B+ 树索引为例(B+ 树索引是数据库中最为常见的一种索引数据结构,几乎所有的关系型数据库都支持它),B+ 树在插入时就要对数据进行排序,其实排序的开销成本并没有多大,那是因为排序是 CPU 操作(当前一个时钟周期 CPU 能处理上亿指令)。如果面对数据顺序或者逆序插入的时候还好,这个时候B+ 树索引维护成本比较低,因为叶子节点都是从左往右进行插入操作,比如自增 ID 的插入、时间的插入(若在自增 ID 上创建索引,时间列上创建索引,则 B+ 树插入通常是比较快的)。

但是如果插入的数据是无序的,B+ 树为了维护排序,需要对页进行分裂、旋转等开销较大的操作,另外,即便对于固态硬盘,随机写的性能也不如顺序写,所以磁盘性能也会收到较大影响。比如用户昵称,每个用户注册时,昵称大多都是随意取的,如果在昵称上创建索引,插入是无序的,索引维护需要的开销会比较大。

2. WHERE条件中用不到的字段不适合建立索引。

这个是为什么呢?索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的。

3. 数据比较少的情况不适合建立索引。

这个是为什么呢?这个很简单,那是因为在数据量不大的情况下,没必要用索引,全表扫描的速度已经很快了,即使你用了索引,索引就发挥不出作用了,没卵用。

4. 唯一性太差的字段不适合建立索引。

这个是为什么呢?这个也很简单,你可以想象一种非常极端的情况,假设数据表中的数据都一样(不可能),你使用索引也一样没卵用。

我们可以以性别这个字段为例,性别无外乎两种可能,男的或者女的(这里别有杠精哈),因为你访问索引需要付出额外的IO开销,你从索引中拿到的只是地址(记住只是地址哦),要想真正访问到数据还是要对表进行一次IO。假如你要从表的100万行数据中取几个数据,那么利用索引迅速定位,访问索引的这IO开销也是非常值了。但如果你是从100万行数据中取50万行数据,就比如性别字段吧,那你相对需要访问50万次索引,再访问50万次表,加起来的开销可想而知。并不会比直接对表进行一次完整扫描小。所以即使你用了索引,没卵用。

5. 参与列计算的列不适合建索引。

这个是为什么呢?这个是因为,如果索引列上有函数运算的话,会导致不走索引,也就是索引失效了 。

举个例子,比如你在在T表上有一个索引Y,但是你的查询语句是这样子SELECT * FROM T WHERE FUN(Y) = XXX。这个时候索引也不会被用到,因为你要查询的列中所有的行都需要被计算一遍。

总结

今天我们一起索引使用相关原则进行了简单梳理,要记住:索引是能够提升SQL 查询的效率,但是索引不是万能的,一定要遵守基本原则。

 

责任编辑:武晓燕 来源: 码上Java
相关推荐

2020-11-24 08:02:26

API接口重构

2021-05-31 09:03:12

算法数据技术

2021-01-27 09:19:44

MySQL数据优化器

2020-12-07 08:04:39

CTO中年公司

2021-05-26 05:40:32

加密勒索软件攻击

2020-12-25 11:37:32

DDoS攻击信用卡黑客

2022-01-13 06:49:23

开源项目删库

2021-09-14 11:57:01

双重勒索勒索软件黑客攻击

2019-09-17 16:04:17

戴尔

2021-02-28 07:52:24

蠕虫数据金丝雀

2021-01-29 14:35:41

代码开发服务器

2020-10-09 09:28:43

互联网数据技术

2019-04-01 15:28:20

996互联网ICU

2020-11-05 14:48:29

AI人工智能互联网

2020-12-03 18:18:46

微信表情下回

2020-05-20 15:37:43

VR虚拟现实年轻人

2012-09-03 14:26:50

云计算亚马逊AWS

2018-07-12 11:49:44

智能手表

2015-07-06 09:39:20

李开复打拼放弃健康
点赞
收藏

51CTO技术栈公众号