mysql中的索引

2020-10-18  本文已影响0人  zfh_51d2

索引

索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。一本 500 页的书,如果你想快速找到其中的某一个知识点,在不借助目录的情况下,那我估计你可得找一会儿。同样,对于数据库的表而言,索引其实就是它的“目录”。

索引的常见模型

索引的出现是为了提高查询效率,但是实现索引的方式却有很多种。介绍下三种常见、也比较简单的数据结构,它们分别是哈希表、有序数组和搜索树。

1.哈希表

哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。



优点:
查询、插入、删除时间复杂度O(1)。
缺点:
哈希表这种结构适用于只有等值查询的场景,无法处理排序的情况

2.有序数组

优点:
等值查询和范围查询时间复杂度O(logn)。
缺点:
插入、删除时间复杂度O(n)。

有序数组索引只适用于静态存储引擎。

3.二叉搜索树

特点:
在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值。
右子树节点的值都大于这个节点的值。
查询、插入、删除时间复杂度O(logn)。

mysql中的索引

一、数据结构角度
1. B+树索引
B+ 树的特点(m叉树):

1.每个节点中子节点的个数不能超过 m,也不能小于 m/2。
2.根节点的子节点个数可以不超过 m/2,这是一个例外。
3.m 叉树只存储索引,并不真正存储数据,这个有点儿类似跳表。
4.通过链表将叶子节点串联在一起,这样可以方便按区间查找。
5.一般情况,根节点会被存储在内存中,其他节点存储在磁盘中。


  树可以有二叉,也可以有多叉。多叉树就是每个节点有多个子节点。
  一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。磁盘随机读一个数据块是很慢的,为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使用二叉树,而是要使用“N 叉”树。这里,“N 叉”树中的“N”取决于数据块的大小。
  以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。这棵树高是 4 的时候,就可以存 1200 的 3 次方个值,这已经 17 亿了。考虑到树根的数据块总是在内存中的,一个 10 亿行的表上一个整数字段的索引,查找一个值最多只需要访问 3 次磁盘。其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。

2.Hash索引

  InnoDB存储引擎会监控对表上各索引页的查询,如果监控到某个索引页被频繁查询,并诊断后发现如果为这一页的数据创建Hash索引会带来更大的性能提升,则会自动为这一页的数据创建Hash索引,并称之为自适应Hash索引。自适应Hash是通过缓冲池中B+树的页进行构建的,建立速度很快,不需要对整张表的数据都构建Hash索引,所以我们又可以把自适应Hash索引看成是索引的索引,。注意一点就是InnoDB只会对热点页构建自适应索引,且是由InnoDB自动创建和删除的,所以不能人为干预是否在一张InnoDB的表中创建Hash索引。


3. Full-Text全文索引

  通过数值比较、范围过滤等就可以完成绝大多数我们需要的查询,但是,如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较。全文索引就是为这种场景设计的。
  like + % 就可以实现模糊匹配了,但like + % 在文本比较少时是合适的,对于大量的文本数据检索是非常慢的。全文索引在大量的数据面前,能比 like + % 快 N 倍,速度不是一个数量级,但是全文索引可能存在精度问题。全文索引的实现是倒排索引。

版本支持:
MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引。
只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。

二、从逻辑角度
三、从物理存储角度

1.聚簇索引
索引B+ Tree的叶子节点存储了整行数据的被称之为聚簇索引。

InnoDB的聚簇索引:

  1. 一个表只能有一个聚簇索引。InnoDB中会对主键建立聚簇索引。
  2. 如果你不指定主键,InnoDB会用一个具有唯一且非空值的索引来代替。
  3. 如果不存在这样的索引,InnoDB会定义一个隐藏的主键,然后对其建立聚簇索引。

2.非聚簇索引
索引B+ Tree的叶子节点只存储了主键的值被称之为非聚簇索引。

覆盖索引
  是指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。 当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。
  因为非聚簇索引只存储了主键的值,所以如果希望通过索引查询主键之外的值的时候,需要通过索引查询到主键,再通过主键的索引查询到完整的数据。需要多查询一次。

索引失效

1.对索引字段做函数操作,可能会破坏索引值的有序性,因此就用不上索引了。
例如:

select count(*) from table where month(t_modified)=7;
select * from table where id + 1 = 10000;

2.隐式类型转换
例如:

select * from table where id=110717;
select * from table where CAST(id AS signed int) = 110717;

如果id 的字段类型是 varchar(32),索引也会失效。

3.隐式字符编码转换。
如果两张表字符集不同,一个是 utf8,一个是 utf8mb4,做关联查询的时候索引也会失效。

4.索引遵循最左前缀原则,是按以%开头的Like模糊查询,索引失效。

使用(B-Tree)索引时,有以下一些技巧和注意事项:

索引设计:

上一篇 下一篇

猜你喜欢

热点阅读