MySQL索引最全详解(看这篇就足够了)

MySQL索引最全详解(看这篇就足够了)-mikechen

MySQL索引定义

MySQL索引就是:数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库中表的数据。

 

MySQL索引作用

索引在数据库中的作用类似于目录在书籍中的作用,用来提高查找信息的速度。

如下图所示:

MySQL索引最全详解(看这篇就足够了)-mikechen

 

MySQL索引类型

MySQL索引类型全面详解(4种最常用索引类型)

MySQL主键索引

1.主键索引简介

主键索引,英文全称Primary Key,简称为主键,主键是一种唯一性索引,每个表只能有一个主键。

 

2.主键索引作用

主键索引可以提高查询效率,并提供唯一性约束,一张表中只能有一个主键。

 

3.主键索引语法

alert table tablename add primary key(`字段名`)

 

4.主键索引原则

在MySQL中,InnoDB数据表的主键设计我们通常遵循几个原则:

1)采用一个没有业务用途的自增属性列作为主键;

2)主键的数据类型最好是数值,比如:编号;

3)主键字段值总是不更新,只有新增或者删除两种操作;

4)不选择会动态更新的类型,比如当前时间戳等。

 

MySQL普通索引

主键索引是在搜索条件为主键的时候才会发挥作用,但是我要以name=’mikechen’为搜索条件怎么办?这就需要涉及普通索引。

对name这种单个列添加的索引叫做普通索引,也叫二级索引。

 

1.普通索引简介

普通索引(index)顾名思义:就是各类索引中最为普通的索引。

 

2.普通索引作用

普通索引最主要的作用:就是提高查询速度。

 

3.普通索引语法

alter table table_name add index(`字段名`);

 

4.普通索引原则

普通索引应该只为那些最经常出现在查询条件(WHERE column =)或排序条件(ORDER BY column)中的数据列创建索引。

只要有可能,就应该选择一个数据最整齐、最紧凑的数据列,比如:一个整数类型的数据列来创建索引。

 

MySQL唯一索引

1.唯一索引简介

mysql中唯一索引的关键字是unique index,唯一索引可以有多个,但索引列的值必须唯一,索引列的值允许有空值。

 

2.唯一索引作用

相对于普通索引,唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。

除此之外还有一个明显的作用:创建唯一索引可以避免数据出现重复。

 

3.唯一索引语法

alter table 表名 add unique(列名)

 

4.唯一索引原则

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

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

 

MySQL全文索引

1.全文索引简介

全文索引指的是:将存储在数据库中的整本书或整篇文章中的任意内容信息查找出来的技术。

 

2.全文索引作用

全文索引与普通的索引不是一回事,在查找上方面其效率是普通模糊(like)查询和N倍,是MySQL专门提供用作搜索引擎的。

 

3.全文索引语法

alter table 表名 add fulltext (列名)

 

4.全文索引原则

全文索引只能用于InnoDB或MyISAM表,只能为CHAR、VARCHAR、TEXT列创建。

 

MySQL索引原理

MySQL索引原理详解(看这篇就够了)

索引是一种高效获取数据的存储结构,所以要理解MySQL索引的原理,必须清楚一种数据结构就是B树或者 B+ 树。

1.B+树

MySQL一般以B+树作为其索引结构,具体有什么特点呢?

  • 所有值按顺序存储,每个叶子到根的距离相同;
  • 非叶子节点不存储数据,只存储指针索引;
  • 叶子节点存储所有数据,不存储指针;
  • 每个叶子节点都有指向相邻下一个叶子节点的指针,即顺序访问指针;

好了说了这么多的 B+ 树的特点,我们来张图看看 B+ 树到底长什么样子。

MySQL索引最全详解(看这篇就足够了)-mikechen

上面的数据页就是实际存放数据页的地方,且数据页之间是通过双向链表进行连接的。

 

2.B+树的查找过程

我们查询一条语句,会通过B+树来查找数据,过程如图所示:

MySQL索引最全详解(看这篇就足够了)-mikechen

主要会经历以下4大步骤:

  1. 如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO。
  2. 在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计。
  3. 通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO。
  4. 29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。

真实的情况是:3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的。

如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。

通过上面的分析,我们知道IO次数取决于B+数的高度H。

如果数据项占的空间越小,数据项的数量越多,树的高度越低,这就是为什么每个数据项,即索引字段要尽量的小,比如:int占4字节,要比bigint8字节少一半。

这也是为什么b+树要求把真实的数据放到叶子节点而不是内层节点,一旦放到内层节点,磁盘块的数据项会大幅度下降,导致树增高。

 

MySQL创建索引语法

MySQL创建索引详解(3种创建方式及5大原则)

MySQL创建索引主要分为以下3种:

1.使用CREATE INDEX创建

create index index_name on table_name(column_name)

 

2.使用ALTER语句创建

修改表结构添加索引,如下所示:

alter table table_name add index index_name(column_name)

 

3.建表的时候创建索引

create table table_name(
  id int not null,
  username varchar(64) not null,
  index [index_name] (username)  
);

 

MySQL创建索引原则

1.最左前缀匹配原则

非常重要的原则,MySQL会一直向右匹配直到遇到范围查询比如:>、<、between、like就停止匹配。

比如:

a = 1 and b = 2 and c > 3 and d = 4

如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

 

2.=和in可以乱序

比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

 

3.尽量选择区分度高的列作为索引

区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少。

 

4.索引列不能参与计算,保持列“干净”

比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引。

原因很简单:b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。

所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

 

5.尽量的扩展索引,不要新建索引

比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可

可以多用查询优化神器 : explain命令。

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法