MySQL夺命连环问2--你对Mysql的索引熟悉是吧?

目录

  • 你对Mysql的索引熟悉是吧?
  • 谈谈你对索引的理解?
  • 谈谈索引的使用场景
  • 说说索引设计的原则
  • 说说索引创建的原则**
  • 创建索引的三种方式,删除索引
  • 索引的底层使用的是什么数据结构?
  • 创建索引时需要注意什么?
  • 谈谈你对 B+ 树的理解?
  • B+树的实现
  • 为什么 InnoDB 存储引擎选用 B+ 树而不是 B 树呢?
  • 谈谈你对聚簇索引的理解?
  • 谈谈你对覆盖索引的认识?
  • 索引的分类?
  • 谈谈你对最左前缀原则、最左匹配原则的理解?
  • 怎么知道创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?
  • 什么情况下索引会失效?即查询不走索引?
  • 查询性能的优化方法?
  • 使用索引查询一定能提高查询的性能吗?为什么
  • 百万级别或以上的数据如何删除
  • 前缀索引
  • B树和B+树的区别
  • 使用B树的好处
  • 使用B+树的好处
  • Hash索引和B+树所有有什么区别或者说优劣呢?
  • 数据库为什么使用B+树而不是B树
  • 为什么B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据?
  • 联合索引是什么?为什么需要注意联合索引中的顺序?
  • 联合索引的创建原则
    • ———————————————— 版权声明:本文为CSDN博主「敖 丙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_35190492/article/details/109257302

你对Mysql的索引熟悉是吧?

谈谈你对索引的理解?

索引是帮助MySQL高效获取数据的数据结构。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。

  • 优点
    可加快数据的检索速度,降低数据库的IO成本。
    通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
    被索引的列会自动进行排序,包括【单列索引】和【组合索引】,只是组合索引的排序要复杂一些。
    如果按照索引列的顺序进行排序,对应order by语句来说,效率就会提高很多。

  • 缺点
    时间方面:创建和维护索引要耗费时间,进行增/改/删表数据时,还要动态维护,会降低增/改/删的执行效率;
    空间方面:需要占物理空间。

谈谈索引的使用场景

where
order by
join(对join语句匹配关系(on)涉及的字段建立索引能够提高效率)
索引覆盖

说说索引设计的原则

  • 出现在where或者连接子句中指定的列
  • 基数要够大的列
  • 使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度节省空间
  • 不要过度索引,只保持需要的索引有利于查询即可

说说索引创建的原则**

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)查询频繁字段适合去创建索引

3)更新频繁字段不适合创建索引

4)不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)

5)尽量扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

6)定义有外键的数据列一定要建立索引。

7)查询中很少涉及的列,重复值比较多的列不要建立索引。

8)定义为text、image和bit的数据类型的列不要建立索引。

创建索引的三种方式,删除索引

第一种方式:在执行CREATE TABLE时创建索引
MySQL夺命连环问2--你对Mysql的索引熟悉是吧?_第1张图片
第二种方式:使用ALTER TABLE命令去增加索引
在这里插入图片描述
ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。

其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。

索引名index_name可自己命名,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。

第三种方式:使用CREATE INDEX命令创建
在这里插入图片描述

删除索引

根据索引名删除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名
在这里插入图片描述

删除主键索引:alter table 表名 drop primary key(因为主键只有一个)。这里值得注意的是,如果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引):
在这里插入图片描述
需要取消自增长再行删除:
MySQL夺命连环问2--你对Mysql的索引熟悉是吧?_第2张图片
但通常不会删除主键,因为设计主键一定与业务逻辑无关。

索引的底层使用的是什么数据结构?

索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有 Hash索引、B+树索引等。而我们经常使用的 InnoDB 存储引擎的默认索引实现为 B+ 树索引。在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;

创建索引时需要注意什么?

  • 非空字段:应该指定列为NOT NULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
  • 取值离散大的字段(变量各个取值之间的差异程度)的列放到联合索引的前面。(可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高)
  • 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高。

谈谈你对 B+ 树的理解?

B+ 树是基于 B 树和叶子节点顺序访问指针进行实现,它具有 B 树的平衡性,并且通过顺序访问指针来提高区间查询的性能。

在 B+ 树中,一个节点中的 key 从左到右非递减排列。

进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。

插入、删除操作会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。

B+树的实现

一个m阶的B+树具有如下几个特征:
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素

为什么 InnoDB 存储引擎选用 B+ 树而不是 B 树呢?

用 B+ 树不用 B 树考虑的是 IO 对性能的影响,B 树的每个节点都存储数据,而 B+ 树只有叶子节点才存储数据,所以查找相同数据量的情况下,B 树的高度更高,IO 更频繁。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。

谈谈你对聚簇索引的理解?

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行
聚簇索引和非聚簇索引的区别
聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。

谈谈你对覆盖索引的认识?

一个索引包含了满足查询语句中字段与条件的数据就叫做覆盖索引。具有以下优点:

  • 索引通常远小于数据行的大小,只读取索引能大大减少数据访问量。
  • 一些存储引擎(例如:MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。
  • 对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。

索引的分类?

聚集索引
非聚集索引

主键索引:数据列不允许重复,不允许为NULL,一个表只能有一个主键。

唯一索引:数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。

普通索引:基本的索引类型,没有唯一性的限制,允许为NULL值。

全文索引:是目前搜索引擎使用的一种关键技术。

谈谈你对最左前缀原则、最左匹配原则的理解?

使用组合索引查询时,mysql会一直向右匹配直至遇到范围查询(>、<、between、like)就停止匹配。
查询的字段不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。

  • 基于最左前缀匹配的索引下推
    在索引遍历过程中,直接对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
    在“仅能利用最左前缀索的场景”下(而不是能利用全部联合索引),对不在最左前缀索引中的其他联合索引字段加以利用——在遍历索引时,就用这些其他字段进行过滤(where条件里的匹配)。过滤会减少遍历索引查出的主键条数,从而减少回表次数,提示整体性能。——在遍历索引的那一步,由只传入可以利用到的字段值,改成了多传入下推字段值。

怎么知道创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?

使用 Explain 命令来查看语句的执行计划,MySQL 在执行某个语句之前,会将该语句过一遍查询优化器,之后会拿到对语句的分析,也就是执行计划,其中包含了许多信息。可以通过其中和索引有关的信息来分析是否命中了索引,例如:possilbe_key、key、key_len 等字段,分别说明了此语句可能会使用的索引、实际使用的索引以及使用的索引长度。

什么情况下索引会失效?即查询不走索引?

1、索引列参与表达式计算。
2、 函数运算。
3、%词语%–模糊查询。
4、 字符串与数字比较不走索引。
5、查询条件中有 or ,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引。
6、正则表达式不使用索引。
7、MySQL 内部优化器会对 SQL 语句进行优化,如果优化器估计使用全表扫描要比使用索引快,则不使用索引。
8、is null不会用,is not null 会用

查询性能的优化方法?

减少请求的数据量
只返回必要的列:最好不要使用 SELECT * 语句。
只返回必要的行:使用 LIMIT 语句来限制返回的数据。
缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的。

减少服务器端扫描的行数
最有效的方式是使用索引来覆盖查询。

使用索引查询一定能提高查询的性能吗?为什么

通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。

索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改。 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O。 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:

  • 基于一个范围的检索,一般查询返回结果集小于表中记录数的30%
  • 基于非唯一性索引的检索

百万级别或以上的数据如何删除

关于索引:由于索引需要额外的维护成本,因为索引文件是单独存在的文件,所以当我们对数据的增加,修改,删除,都会产生额外的对索引文件的操作,这些操作需要消耗额外的IO,会降低增/改/删的执行效率。所以,在我们删除数据库百万级别数据的时候,查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的。

  • 所以我们想要删除百万数据的时候可以先删除索引(此时大概耗时三分多钟)
  • 然后删除其中无用数据(此过程需要不到两分钟)
  • 删除完成后重新创建索引(此时数据较少了)创建索引也非常快,约十分钟左右。
  • 与之前的直接删除比绝对是要快速很多,更别说万一删除中断,一切删除会回滚。那更是坑了。

前缀索引

语法:index(field(10)),使用字段值的前10个字符建立索引,默认是使用字段的全部内容建立索引。

前提:前缀的标识度高。比如密码就适合建立前缀索引,因为密码几乎各不相同。

实操的难度:在于前缀截取的长度。

我们可以利用select count(*)/count(distinct left(password,prefixLen));,通过从调整prefixLen的值(从1自增)查看不同前缀长度的一个平均匹配度,接近1时就可以了(表示一个密码的前prefixLen个字符几乎能确定唯一一条记录)

B树和B+树的区别

在B树中,你可以将键和值存放在内部节点和叶子节点;但在B+树中,内部节点都是键,没有值,叶子节点同时存放键和值。

B+树的叶子节点有一条链相连,而B树的叶子节点各自独立。
MySQL夺命连环问2--你对Mysql的索引熟悉是吧?_第3张图片

使用B树的好处

B树可以在内部节点同时存储键和值,因此,把频繁访问的数据放在靠近根节点的地方将会大大提高热点数据的查询效率。这种特性使得B树在特定数据重复多次查询的场景中更加高效。

使用B+树的好处

由于B+树的内部节点只存放键,不存放值,因此,一次读取,可以在内存页中获取更多的键,有利于更快地缩小查找范围。 B+树的叶节点由一条链相连,因此,当需要进行一次全数据遍历的时候,B+树只需要使用O(logN)时间找到最小的一个节点,然后通过链进行O(N)的顺序遍历即可。而B树则需要对树的每一层进行遍历,这会需要更多的内存置换次数,因此也就需要花费更多的时间

Hash索引和B+树所有有什么区别或者说优劣呢?

首先要知道Hash索引和B+树索引的底层实现原理:

hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据。B+树底层实现是多路平衡查找树。对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。

那么可以看出他们有以下的不同:

  • hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询。

因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询。而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围。

  • hash索引不支持使用索引进行排序,原理同上。
  • hash索引不支持模糊查询以及多列索引的最左前缀匹配。原理也是因为hash函数的不可预测。AAAA和AAAAB的索引没有相关性。
  • hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询。
  • hash索引虽然在等值查询上较快,但是不稳定。性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差。而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。

因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度。而不需要使用hash索引。

数据库为什么使用B+树而不是B树

  • B树只适合随机检索,而B+树同时支持随机检索和顺序检索;
  • B+树空间利用率更高,可减少I/O次数,磁盘读写代价更低。索引往往以文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗。B+树的内部结点并没有指向关键字具体信息的指针,只是作为索引使用,其内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了;
  • B+树的查询效率更加稳定。B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找。而在B+树中,顺序检索比较明显,随机检索时,任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当。
  • B-树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。
  • B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作。
  • 增删文件(节点)时,效率更高。因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率。

为什么B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据?

在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引。 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引。如果没有唯一键,则隐式的生成一个键来建立聚簇索引。

当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询。

联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。

因为要利用上最左前缀匹配原则减少浪费。

  • 第一原则是复用,最左前缀原则,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
  • 第二原则是空间,用不上最左前缀,如果是高频的查询,就再建一个单独的索引,当然我们可以选择交换顺序,争取建立的索引占用的内存越小

联合索引的创建原则

在创建联合索引的时候因该把频繁使用的列、区分度高的列放在前面,频繁使用代表索引利用率高,区分度高代表筛选粒度大,这些都是在索引创建的需要考虑到的优化场景,也可以在常需要作为查询返回的字段上增加到联合索引中,如果在联合索引上增加一个字段而使用到了覆盖索引,那我建议这种情况下使用联合索引。

————————————————
版权声明:本文为CSDN博主「敖 丙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35190492/article/details/109257302

感谢大佬的文章,原文传送门这里!!!!!!!!!!!
————————————————
版权声明:本文为CSDN博主「ThinkWon」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ThinkWon/article/details/104778621

你可能感兴趣的:(mysql夺命连环问系列,mysql,数据库,sql)