关于MySQL索引,我的整理都在这了

索引

什么是索引?

索引类似于书籍的目录,想找到书中某一个内容,我们需要先去找到对应的目录,定位对应的页码,MySQL存储引擎就是使用类似的方式进行查询,先去索引中查找对应的值,然后找根据匹配的索引值找到对应的行。

索引有什么好处?

1、提高数据的检索效率,降低数据库IO成本:使用索引的目的就是可以缩小表中需要查询的记录从而加快数据检索速度。
2、降低数据的排序成本,降低CPU的消耗:索引之所以查的快,是因为它先对数据进行排序,若该字段正好需要排序,则降低了数据排序的成本。

索引有什么坏处?

1、占用额外的存储空间,它本质上就是一张表,它存着主键和索引字段,在磁盘上以索引文件的形式存在
2、数据更新效率变低,如果数据进行了更新的话,那么对应的索引也需要更新,从而降低了数据更新的速度。否则索引指向的物理数据可能不对,这也是索引失效的一个原因

索引的类型?

索引都是存储在存储引擎层的,主要有以下6种:

  1. 普通索引:最普通的索引,没有任何约束
  2. 唯一索引:与普通索引类似,但有唯一性约束
  3. 主键索引:特殊的唯一索引,不能有空值
  4. 联合索引:将多个列组合在一起创建索引,可以覆盖多个列
  5. 外键索引:只有InnoDB才支持使用外键索引,为了保持数据的一致性、完整性和级联操作
  6. 全文索引:MySQL自带的全文索引,只支持InnoDB和MyISAM,并且只能对英文检索,一般适用全文检索引擎。

索引的“创建”原则?

  1. 最适合索引出现的地方是where子句中出现的列,而不是select后出现的列
  2. 索引列的基数越大,索引效果越好
  3. 根据情况创建联合索引,可以提高查询的效率
  4. 避免创建过多的索引,索引会额外的占用空间,降低写的效率
  5. 主键应该尽可能的选择长度较短的数据类型,这样可以有效的减少索引的磁盘占用提高查询效率
  6. 对字符串进行索引,应该定制一个前缀长度,可以节省大量的空间。

为什么要使用索引?

一句话:因为索引可以让我们避免全表扫描去查数据,提高了查询效率。
全表扫描:全表扫描就是将整张表的数据全部或者分批次的加载到内存中,存储的最小单位是块或者页,它们是由多行数据来组成的,然后我们将这些块加载到内存里,然后通过轮询的方式去查找数据,找到我们需要的数据,然后返回。通常意义上,我们认为这样的查询方式是比较慢的,但也不是绝对意义的,当数据量很小的情况下,通过全盘扫描的效率更高,毕竟是基于内存的呀,肯定效率是比较快的。

什么样的信息能成为索引?

简单回答一下就是:主键、唯一键或者普通键,只要具备区分一定数据的都可以作为索引

索引的数据结构?

简介

当前主流的就是B+树,还有Hash结构和BitMap等,其中MySQL不支持BitMap结构,同时基于InnoDB和MyISAM引擎的MySQL不显示的支持Hash结构。

分析利弊

B+树

在说B+树之前,先说一下二叉查找树、B树

  1. 二叉查找树是也可以做查找,时间复杂度是O(log n),但是它每个树的子节点就只有两个,不符合条件的话,需要再进入到下层查找,系统瓶颈在于IO,这样的话,数据量一旦大了,就会出现系统瓶颈,并且还有一个极端情况,如果数据都插入到树的一边,使得这个二叉树成了链表,时间复杂度就是O(n)
  2. B树的话,它在更新数据的时候,B树会根据它的特性进行合并和拆解,达到平衡,不会像二叉查找树那样出现极端情况,但也有其他的问题,就例如在查找的时候是范围查找,那么B树就会出现系统瓶颈了,会多次IO。
  3. 最后说一下B+树,不同于B树的情况,它的叶子节点底层是通过链表连接起来的,可解决范围查找导致多次IO的情况。

Hash结构

hash结构呢,它就将关键字当做key,数据作为值来进行存储。它只适用于==或者in来进行检索,不支持范围查找,因为它是根据关键字来进行计算hash值的,所以只是某个关键字的一部分是不会找到这个数据的。而且它也不支持比较查找,因为,根据索引计算的hash值是不能确定原数据的大小的。它还有一个弊端如果在极端情况下,根据关键字的计算出的key然后定位到同一个桶中,那么它的结构也成了线性的了,查询效率倒不如B+树了。

BitMap

它的锁粒度是非常大的,它在进行插入或者更新数据的时候,跟这个数据在同一个位图的数据操作都会被锁住,并不适合在高并发的情况下的联机处理系统。

它适合在并发较少,统计较多的场景中使用。

结论

最后常用的就是B+树了,下面总结下为什么它是常用的:

  1. 它的数据存储在叶子结点,而非叶子节点存储的是这条数据对应的关键字,言外之意就是,非叶子节点就能存储更多的关键字,这样通过一次IO就能检索到更多的关键字,然后就会降低IO次数,提高查询效率
  2. 它的查询时间复杂度是非常稳定的,它的一次查询一定是要经历根节点到叶子结点的查询过程,时间复杂度是O(log n)
  3. 它更利于对数据库的扫描,支持范围查询。

聚簇索引与非聚簇索引?

这块的知识点,就由InnoDB和MyISAM两个存储引擎考虑开始。

什么是聚簇索引?什么是非聚簇索引

聚簇索引的结构中:它的叶子结点包含的是对应的一条真正的数据。
非聚簇索引的结构中:它的叶子结点包括就只是索引值的信息和该行数据对应的物理地址。

MyISAM和InnoDB中的区别

MyISAM中不论是主键索引、唯一键索引和普通键索引,它都是非聚簇索引。
InnoDB中除了非聚簇索引,它还生成一个聚簇索引。InnoDB中的非聚簇索引的叶子结点包含的是主键索引信息。如果在设计表的时候指定了主键,那么这个主键生成的索引结构就是聚簇索引,如果没有指定,那就会指定该表的第一个唯一非空索引作为聚簇索引,再不满足的话,InnoDB内部会生成一个隐藏主键(密集索引),这个隐藏主键是一个6字节的列,该列的值会随着数据的插入而自增,也就是说我们的InnoDB必须有一个主键,而该主键就必须作为唯一的密集索引

因为InnoDB的主键索引和数据本身是存储在同一个文件当中的,因此在加载主键索引的文件的同时也将数据加载了进去。通过稀疏索引查找元素的话,会通过稀疏索引的B±Tree中检索该键,定位到主键信息,然后再进行一步操作,通过主键信息在主键索引中做检索操作,找到该行信息,这里就会出现一个覆盖索引的考点,如果select中查找的就是某个索引值的话,那么就不会进行回表查询了,这也就是常说的覆盖索引的情况

而MyISAM采用稀疏索引,主键索引放在一个文件,辅助键索引放在一个地方,而数据信息放在一个 独立的文件当中。两个索引的叶子结点都使用的是指向该文件的地址信息

表结构信息存储在 xxx.frm文件中,在InnoDB中,索引和数据都存储在 xxx.ibd文件中,而MyISAM的索引和数据是分开的,索引存放在xxx.MYI中,数据存放在xxx.MYD中的

索引相关题目

如何定位并优化慢查询SQL?

首先会根据慢日志定位慢查询SQL,慢日志用来记录我们执行比较慢的SQL,如果一条SQL执行时间超过了10秒钟(默认),这条记录就会被放入到慢日志文件中。

可以使用explain等工具分析SQL

修改SQL,或者让SQL尽量走索引

联合索引的最左匹配成因?

什么是最左匹配原则?

假如我们现在使用联合索引,利用多个列创建一个索引(a,b),此时我们有一个查询语句:select * from table where a=xx and b=xx,他就可以使用到这个联合索引,而select * from table where b=xx就不能走这个联合索引了。

最左匹配:MySQL会根据where语句中的信息,从左往右一直找,直到遇到(<,>,between,like)就停止匹配,比如a=3 and b=4 and c>5 and d=6,这样一个信息,那么(a,b,c,d)这样一个联合索引就用不到了,而(a,b,d,c)这样一个索引就会被用到。a,b,c,d的顺序可以调整

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

为什么会有这样的成因呢:因为存储引擎会根据这个联合字段创建一个B+树,然后第一层就是a,也就是索引最左边的字段,它对应的元素是最左的,然后找到沿着符合a值的节点继续往下找。所以,如果一开始检索不是通过a字段来的,那么它就不会通过这个索引找到任何值。

索引是建立的越多越好吗?

答案肯定是否定的呀!假如我们的数据的量很少,但是索引建立的那么多,就相当于书的页数本来就少,我本可以通过从头找就很快找到,但是建立了很多的目录,先去找目录,然后根据目录再来找值,那不是费二遍事吗?哈哈。并且建立很多的索引,维护起来也很麻烦。所以综上来说,索引并不是建立的越多越好!

猜你喜欢

转载自blog.csdn.net/MarkusZhang/article/details/108397811