创建索引的注意事项

目录

一.11种适合创建索引的常见情况

1. 字段的数值有唯一性的限制

2. 频繁作为 WHERE 查询条件的字段

3. 经常 GROUP BY 和 ORDER BY 的列

4. UPDATE、DELETE 的 WHERE 条件列

5.DISTINCT 字段需要创建索引

6. 多表 JOIN 连接操作时,创建索引注意事项

7. 使用列的类型小的创建索引

8. 使用字符串前缀创建索引

9. 区分度高(散列性高)的列适合作为索引

10. 使用最频繁的列放到联合索引的左侧

11. 在多个字段都要创建索引的情况下,联合索引优于单值索引

二.7种不适合创建索引的常见情况

1. 在where中使用不到的字段,不要设置索引

2. 数据量小的表最好不要使用索引

3. 有大量重复数据的列上不要建立索引

4. 避免对经常更新的表创建过多的索引

5. 不建议用无序的值作为索引

6. 删除不再使用或者很少使用的索引

7. 不要定义冗余或重复的索引

① 冗余索引

② 重复索引

特别鸣谢:


一.11种适合创建索引的常见情况

1. 字段的数值有唯一性的限制

业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。(来源:Alibaba)

说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的。

2. 频繁作为 WHERE 查询条件的字段

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

比如学生表数据表(含100万条数据),我们肯定会经常用到学生的学号和姓名等。

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 条件过滤是非常可怕的。

        最后, 对用于连接的字段创建索引 ,并且该字段在多张表中的 类型必须一致 。比如 course_id 在student_info 表和 course 表中都为 int(11) 类型,而不能一个为 int 另一个为 varchar 类型,因为类型不一样时数据库是会做隐式类型转换的,而做了类型转换的sql是不走索引的。

7. 使用列的类型小的创建索引

        我们这里所的类型大小指的就是该类型表示的数据范围的大小。 我们在定义表结构的时候要显式的指定列的类型, 以整数类型为例, 有TINYINT 、INT , BIGINT 等, 它们占用的存储空间依次递增, 能表示的整数范围当然也是依次递增。如果我们想要对某个整数列 建立索引的时,在表示的整数范围允许的情况下, 尽量让索引列使用较小的类型, 比如我们能使INT 就不要使 BIGINT。这是因为:

  • 数据类型越小,在查询时进行的交操作越快
  • 数据类型越小,索引占用的存储空间就越少, 在一个数据页内就可以放下更多的记录, 从而减少磁I/0 带 来的性能损耗,也就意味着可以把更多的数据页缓存在内存中, 从而加快读写效率。

这个建议对于表的主键来说更加适用, 因为不仅是聚簇索引中会存储主键值, 其他所有的二级索引的节点处都会存储一份记录的主键值, 如果主诞使甲更小的数据类型, 也就意味着节省更多的存储空间和更高效的。

8. 使用字符串前缀创建索引

拓展: Alibaba 《Java 开发手册》
强制 】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。
 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会 高达90% 以上 ,可以使用 count(distinct left( 列名 , 索引长度 ))/count(*) 的区分度来确定。

9. 区分度高(散列性高)的列适合作为索引

10. 使用最频繁的列放到联合索引的左侧

这样也可以较少的建立一些索引。同时,由于"最左前缀原则",可以增加联合索引的使用率。

11. 在多个字段都要创建索引的情况下,联合索引优于单值索引

二.7种不适合创建索引的常见情况

1. 在where中使用不到的字段,不要设置索引

2. 数据量小的表最好不要使用索引

3. 有大量重复数据的列上不要建立索引

举例1:要在 100 万行数据中查找其中的 50 万行(比如性别为男的数据),一旦创建了索引,你需要先访问 50 万次索引,然后再访问 50 万次数据表,这样加起来的开销比不使用索引可能还要大。

结论:当数据重复度大(比如 高于 10% 的时候),也不需要对这个字段使用索引。

4. 避免对经常更新的表创建过多的索引

5. 不建议用无序的值作为索引

例如身份证、UUID(在索引比较时需要转为ASCII,并且插入时可能造成页分裂)、MD5、HASH、无序长字符串等。

6. 删除不再使用或者很少使用的索引

7. 不要定义冗余或重复的索引

① 冗余索引

举例:建表语句如下
CREATE TABLE person_info(
id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
name VARCHAR ( 100 ) NOT NULL ,
birthday DATE NOT NULL ,
phone_number CHAR ( 11 ) NOT NULL ,
country varchar ( 100 ) NOT NULL ,
PRIMARY KEY (id),
KEY idx_name_birthday_phone_number (name( 10 ), birthday, phone_number),
KEY idx_name (name( 10 ))
);
通过 idx_name_birthday_phone_number 索引就可以对 name 列进行快速搜索,再创建一 个专门针对 name 列的索引就算是一个 冗余索引 ,维护这个索引只会增加维护的成本,并不会对搜索有什么好处。

② 重复索引

另一种情况,我们可能会对某个列 重复建立索引 ,比方说这样:
CREATE TABLE repeat_index_demo (
col1 INT PRIMARY KEY ,
col2 INT ,
UNIQUE uk_idx_c1 (col1),
INDEX idx_c1 (col1)
)
我们看到, col1 既是主键、又给它定义为一个唯一索引,还给它定义了一个普通索引,可是主键本身就会生成聚簇索引,所以定义的唯一索引和普通索引是重复的,这种情况要避免。

最后敲黑板:“限制索引的数目

特别鸣谢:

以上知识来源于“尚硅谷”,宋红康老师的《MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!》系列课程。

所以本文章看不懂的卷王们可以去搜索宋红康老师的mysql系列课程。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值