MySQL索引

1. 索引数据结构

对于索引可以这样理解:

原本没有索引的表,是进行全表扫描,数据一行一行筛选,有了索引,数据有了结构,大大增加查询效率。

MySQL索引_第1张图片

所以,索引可以大大提高我们的查询效率。(当然索引结构不是简单的二叉树,这里只是举个例子)

关于二叉树,对于数据检索有一个明显的缺点,就是当数据时顺序插入时(从大到小或从小到大逐一插入),会形成一个链表,导致查询效率大大降低。

MySQL索引_第2张图片

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包括以下几种:

MySQL索引_第3张图片

MySQL索引_第4张图片 我们平常说的索引,如果没有特别指明,一般说的都是B+树结构的索引。

这里推荐一个数据结构可视化网址: Data Structure Visualization (usfca.edu)

里面可以详细的看到数据结构的演变过程,包括B树、B+树;(好用,爱用)

Btree(B树结构)

又叫做多路平衡查找树,以一颗最大度数(max-degree)为5(5阶)的b-tree为例(每个节点最多存放4个key,5个指针)

节点中每次存放的数据大于4,就会取中间数向上分裂,具体演变过程可以参考数据可视化网站。对于B数,每个key下面都是一个数据。

MySQL索引_第5张图片
B+tree(B+树结构)

MySQL索引数据结构对经典的B+Tree进行了优化。在原BTree的基础上,增加一个指向相邻叶子节点的链表指针,指针的B+Tree,提高区间访问的性能。且数据都存储在叶子节点中,父节点只是起到了一个指向作用。

MySQL索引_第6张图片

具体演变过程参考如上。 

Hash结构

哈希索引就是采用一定的哈希算法,将键值换成新的hash值,映射到对应的槽位上,然后存储在hash表中。如果不同数据映射到了同一个槽位上,会形成链表。

MySQL索引_第7张图片MySQL索引_第8张图片思考:为什么InnoDB引擎要使用B+tree作为索引结构?

1. 相对于二叉树,层级更少,搜索效率高; 

2. 对于B-tree, 无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

3.对于Hash,如上图。

2. 索引的使用

1. 分类

索引主要包括四种:主键索引、唯一索引、常规索引和全文索引

MySQL索引_第9张图片在InnoDB引擎中,根据索引的形式,又可以分为聚集索引(聚簇索引)和二级索引 (非聚簇索引)

MySQL索引_第10张图片 聚集索引选取规则:如果存在主键,主键索引就是聚集索引,如果不存在主键,将使用唯一索引作为聚集索引。如果没有主键且没有唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

聚集索引下放的是行数据,而二级索引叶子节点下方的是代表这个数据的键。如下图所示

MySQL索引_第11张图片

举个例子,当我们查询select * from user where id = 5时,走的就是聚集索引,而当我们查询select * from name = 'Kit'时,是先走二级索引拿到id值,然后在走聚集索引拿到行数据。这也就是为啥select * from user where id = ? 速度要快于select * from user where id where name = ?

补充:InnoDB引擎中的B+tree树有多高?

假设一行数据大小为1k,一页可以存储16行数据,InnoDB的指针需要占据6个字节的空间,主键即使为bigint,占用字节为8。则:

高度为2时 n * 8 +(n+1) * 6 = 16 * 1024 ,得到n = 1170;所以它能够存储的数据量为1171 * 16 = 18736

高度为3则可以存储的数据量为1171 * 1171 * 16 = 2193856;

2. 索引的语法

创建索引 

CREATE [UNIQUE|FULLTEXT] INDEX idx_name on table_name(idx_col_name)

查看索引

show index from tb_user;

删除索引

DROP INDEX idx_name on table_name;

MySQL索引_第12张图片

-- name字段为姓名字段,该字段可能会重复(创建普通索引)
create index idx_user_name on tb_user(name);

-- phone为手机号,是非空且唯一的(创建唯一索引)
create unique idx_user_phone on tb_user(phone);

-- 为profession age status创建索引(联合索引)
create index idx_user_pro_age_sta on tb_user(profession,age,status);

-- 为email创建合适的索引
create index idx_user_email from tb_user(email);

3. sql性能分析

查看sql语句执行评率

Mysql客户端连接成功后,可以通过执行show [session|global] status like 'Com______';来查看 select、insert等增删改查语句的执行频率。

show [session|global] status like 'Com_______';

MySQL索引_第13张图片

慢查询日志

慢查询日志中纪录了执行时间超过指定参数的所有sql语句的日志。

MySQL默认的慢查询日志没有开启,需要在MySQL的配置文件中(/etc/my.cnf)中配置如下信息

MySQL索引_第14张图片

生成出来的慢查询日志文件位置在/var/lib/mysql 中

profiles

show profiles能够在帮我们优化sql的时候了解时间都耗费到哪里去了,通过hava_profile参数,能够看到当前MySQL是否支持profiles 

MySQL索引_第15张图片MySQL索引_第16张图片

MySQL索引_第17张图片 MySQL索引_第18张图片

MySQL索引_第19张图片

explain

explain可以查看当前sql语句的执行计划

出现的表格中各个列代表的意思如下图 MySQL索引_第20张图片

MySQL索引_第21张图片4. 索引使用规则

最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)

表中存在如下联合索引,最左索引为profession,其次是age,status

MySQL索引_第22张图片

如果where条件中保留最左侧列(profession),联合索引始终存在。

否则,索引失效

 且如果跳过了索引的字段(age),索引仍然会失效

索引失效情况

 1. 不要在索引上进行函数运算,否则索引会失效

MySQL索引_第23张图片

MySQL索引_第24张图片

2. 如果查询字符串不加引号,索引失效 

3.如果使用了模糊查询,如果只是尾部模糊查询,索引不会失效,如果是头部模糊查询,索引失效。

 4. 用or分隔开的条件,如果or前的条件的列中有索引,而后面的列中没有索引,则涉及到的索引都不会生效。

MySQL索引_第25张图片

5. 数据评估影响,如果MySQL 评估使用索引比全表更慢,索引会失效。

即添加的where条件,表中数据大部分满足此条件,索引会失效。

查询手机号(phone)> 17799990000时,索引失效

5. SQL提示 

有时候一个字段涉及多个索引,MySQL会自动进行评估选择一个索引,有时候这个索引并不是我们本意使用的索引。而SQL提示,就是在SQL语句中加入一些提示来达到优化操作的目的。

 user index:建议数据库使用某个索引,不一定被采纳

explain select * from tb_user use index(index_user_pro) where prefession = '软件工程'

 ignore index: 不允许用某个索引

explain select * from tb_user ignore index(index_user_pro) where prefession = '软件工程'

force index 强制使用某个索引

explain select * from tb_user force index(index_user_pro) where prefession = '软件工程'

6. 前缀索引

当字段类型为字符串(varchar, text等 )时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀建立索引,这样可以大大节约索引空间,从而提高索引效率。

前缀长度如何选择?

前缀长度.
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

可以用如下SQL查询选择性(不重复数/总数,为1时最优)

MySQL索引_第26张图片

针对email字段创建索引

create index idx_user_email_5 from tb_user(email(5))

MySQL索引_第27张图片 7. 索引设计原则

MySQL索引_第28张图片 

你可能感兴趣的:(SQL学习,mysql,数据库)