上篇文章讲到使用MySQL的Explain命令可以分析SQL性能瓶颈,优化SQL查询,以及查看是否用到了索引。

我们都知道创建索引可以提高查询效率,但是具体该怎么创建索引?

哪些字段适合创建索引?

哪些字段又不适合创建索引?

本文跟大家一块学习一下如何创建合适数据库索引。

1. MySQL索引的分类

在创建索引之前了解一下MySQL有哪些索引,然后我们才能选择合适的索引。

常见的索引有,普通索引、唯一索引、主键索引、联合索引、全文索引等。

普通索引

普通索引就是最基本的索引,没有任何限制。

可以使用命令创建普通索引:

ALTER TABLE `table_name` ADD INDEX index_name (`column`);

唯一索引

与普通索引不同,唯一索引的列值必须唯一,允许为null。

创建方式是这样的:

ALTER TABLE `table_name` ADD UNIQUE index_name (`column`);

主键索引

主键索引是一种特殊的唯一索引,并且一张表只有一个主键,不允许为null。

创建方式是这样的:

ALTER TABLE `table_name` ADD PRIMARY KEY (`column`);

联合索引

联合索引是同时在多个字段上创建索引,查询效率更高。

创建方式是这样的:

ALTER TABLE `table_name` ADD INDEX index_name (`column1`, `column2`, `column3`);

全文索引

全文索引主要用来匹配字符串文本中关键字。

当需要字符串中是否包含关键字的时候,我们一般用like,如果是以%开头的时候,则无法用到索引,这时候就可以使用全文索引了。

创建方式是这样的:

ALTER TABLE `table_name` ADD FULLTEXT (`column`);

2. 哪些字段适合创建索引?

我总结了有以下几条:

2.1 频繁查询的字段适合创建索引

一张表的字段总会有冷热之分,很明显那些频繁使用的字段更适合为它创建索引。

2.2 在where和on条件出现的字段优先创建索引

为什么不是在select后面出现的字段优先创建索引?

因为查询SQL会先匹配on和where条件的字段,具体的匹配顺序是这样的:

from > on > join > where > group by > having > select > distinct > order by > limit

2.3 区分度高的字段适合创建索引

比如对于一张用户表来说,生日比性别的区分度更高,更适合创建索引。

可以使用下面的方式手动统计一下,每个字段的区分度,值越大,区分度越高:

select
count(distinct birthday)/count(*),
count(distinct gender)/count(*)
from user;

对于已经创建好的索引,我们还可以使用MySQL命令查看每个索引的区分度排名:

图中Cardinality列表示索引的区分度排名,也被称为基数。

2.4 有序的字段适合创建索引

有序的字段在插入数据库的过程中,仍能保持B+树的索引结构,不需要频繁更新索引文件,性能更好。

3. 哪些字段不合适创建索引?

说完哪些字段适合创建索引,就有不适合创建索引的的字段。

3.1 区分度低的字段不适合创建索引。

刚才说了用户表中性别的区分度较低,不如生日字段适合创建索引。

3.2 频繁更新的字段不适合创建索引

更新字段的过程中,需要维护B+树结构,会频繁更新索引文件,降低SQL性能。

3.3 过长的字段不适合创建索引

过长的字段会占用更多的空间,不适合创建索引。

3.4 无序的字段不适合创建索引

无序的字段在插入数据库的过程中,为了维护B+树索引结构,需要频繁更新索引文件,性能较差。

4. 创建索引的其他注意事项

4.1 优先使用联合索引

查询的时候,联合索引比普通索引能更精准的匹配到所需数据。

图中就是在(age,name)两个字段上建立的联合索引,在B+树中的存储结构。

可以看出,是先age排序,age相等的数据,再按name排序。

对于这条查询SQL:

select age,name from user where age=18 and name='李四';

联合索引只需一次就可以查到所需数据,如果我们只在age字段上建立索引,会先匹配到age=18的三条数据,然后再逐个遍历,效率更差,所以平时应该优先使用联合索引。

4.2 使用联合索引时,区分度的字段放前面

这样可以减少查询次数,更快地匹配到所需数据。

4.3 过长字符串可以使用前缀索引

比如在匹配用户地址的时候,如果乡镇已经能区分大部分用户了,就没必要精确到街道小区了。

创建普通索引的时候,指定索引长度,就可以创建前缀索引了。

ALTER TABLE `user` ADD INDEX idx_address (address(3));

4.4 值唯一的字段,使用唯一索引

使用唯一索引,可以避免程序bug导致产生重复数据。

4.5 排序和分组字段也尽量创建索引

在order by和group by中的字段也尽量创建索引,避免使用文件排序,可以使用索引排序提供性能。

4.6 避免创建过多索引

索引好用,适度即可。创建过多的索引,会占用更多存储空间,也会严重影响SQL性能,每次更新SQL,都需要更新大量索引文件,得不偿失。

知识点总结:

文章持续更新,可以微信搜一搜「 一灯架构 」第一时间阅读更多技术干货。

精心总结十三条建议,帮你创建更合适的MySQL索引的更多相关文章

  1. 10条建议帮助你创建更好的jQuery插件

    本文总结了帮助你创建更好jQuery插件的10条建议.分享给大家供大家参考.具体说明如下: 在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就 ...

  2. 转:10条建议让你创建更好的jQuery插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了.使 ...

  3. 10 条建议让你创建更好的 jQuery 插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了. ...

  4. 10条建议让你创建更好的jQuery插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了.使 ...

  5. 10条建议让你创建更好的jQuery插件(转载)

    为了避免重复造轮子,自己手动开发jquery 插件,让小组其他成员可以直接使用.学习开发中,看到Phillip Senn 写的 关于jquery 插件开发注意10点,转载之! ------------ ...

  6. 精心整理16条MySQL使用规范,减少80%问题,推荐分享给团队

    上篇文章介绍了如何创建合适的MySQL索引,今天再一块学一下如何更规范.更合理的使用MySQL? 合理规范的使用MySQL,可以大大减少开发工作量和线上问题,并提升SQL查询性能. 我精心总结了这16 ...

  7. MySQL如何创建一个好索引?创建索引的5条建议【宇哥带你玩转MySQL 索引篇(三)】

    MySQL如何创建一个好索引?创建索引的5条建议 过滤效率高的放前面 对于一个多列索引,它的存储顺序是先按第一列进行比较,然后是第二列,第三列...这样.查询时,如果第一列能够排除的越多,那么后面列需 ...

  8. 提高Axure设计效率的10条建议

    http://www.woshipm.com/ucd/92153.html Axure 是创建软件原型的快速有力的工具.上手很容易,但是,其中存在一个危险.这款软件是如此的直观以至于很多用户可以在没有 ...

  9. 提高Axure设计效率的10条建议 (转)

    Axure 是创建软件原型的快速有力的工具.上手很容易,但是,其中存在一个危险.这款软件是如此的直观以至于很多用户可以在没有接受过任何正式培训的情况下进行使用.他们可能不知道的是他们可能没有以恰当的方 ...

随机推荐

  1. 关于『进击的Markdown』:第一弹

    关于『进击的Markdown』:第一弹 建议缩放90%食用 比起隐蔽物下的狙击手,Markdown更像冲锋陷阵的阵头兵 简单.粗暴.直接.而且好上手 各位晚上好! 早饭吃了吗您 我 今 天 没 吃 M ...

  2. 变量作用域——JavaSE基础

    变量作用域 局部变量.成员变量.静态变量的区别 类型 声明位置 从属于 生命周期 局部变量 方法或语句块内部 方法/语句块 从声明位置开始,直到方法或语句块执行完毕,局部变量消失 成员变量 (实例变量 ...

  3. Keil软件下用Jlink无法识别芯片

    Keil软件下用Jlink无法识别芯片 硬件:正点原子探索者 软件:keil J-Link固件版本:V9.40 J-Link V6.94b驱动:下载地址 跟着视频教程走,发现的第一个问题就是这个,记录 ...

  4. np.r_、np.c_、np.concatenate和np.append

    np.r_是按行连接两个矩阵,就是把两矩阵上下相加,要求列数相等,最终结果的行数为两个矩阵行数和. np.c_是按列连接两个矩阵,就是把两矩阵左右相加,要求行数相等,最终结果的列数等于两矩阵的列数和. ...

  5. 【Java面试】数据库连接池有什么用?它有哪些关键参数?

    一个工作5年的粉丝找到我,他说参加美团面试,遇到一个基础题没回答上来. 这个问题是:"数据库连接池有什么用?以及它有哪些关键参数"? 我说,这个问题都不知道,那你项目里面的连接池配 ...

  6. 这就是艺术「GitHub 热点速览 v.22.25」

    作者:HelloGitHub-小鱼干 不知道写了那么久代码的你,是否还记得"代码写诗"这个词,它是用来形容代码的优雅.但是本周的项目,虽然你看到的是代码的成品,也会惊讶于它的艺术感 ...

  7. 关于各种Vue UI框架中加载进度条的正确使用

    这里拿MUSE UI 中的进度条举例 <mu-circular-progress :size="40" class="icon" v-if="i ...

  8. wcf .net webService和 .net webApi的联系与差异

    首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...

  9. ASP.NET MVC的核心-Controller(控制器)

    "每一个请求都必须通过Controller处理,然而其中有些请求是不需要模型和视图的" MVC框架规定带Controller后缀的类称为所谓的"控制器",在xx ...

  10. 一文详解|Go 分布式链路追踪实现原理

    在分布式.微服务架构下,应用一个请求往往贯穿多个分布式服务,这给应用的故障排查.性能优化带来新的挑战.分布式链路追踪作为解决分布式应用可观测问题的重要技术,愈发成为分布式应用不可缺少的基础设施.本文将 ...