写点什么

探究 MYSQL 之索引

作者:C++后台开发
  • 2022 年 9 月 29 日
    湖南
  • 本文字数:2888 字

    阅读完需:约 9 分钟

探究MYSQL之索引

在讲 MYSQL 的索引之前,先了解一下 MYSQL 的 B+树,首先它是多路平衡搜索树,为什么 MYSQL 使用的是 B+树,因为数据存储在磁盘中,而树的高度决定了访问磁盘的次数,所以选择 B+树;MYSQL 的 B+树结构如下图所示:

​  MYSQL 的 B+树它具有以下特点:

  (1)叶子节点当中存储所有的数据

  (2)非叶子节点当中只存储所有索引信息(key 用来排序)

  (3)B+树的高度代表访问磁盘的次数

  (4)节点默认的大小是 16K,即一页(磁盘管理的最小单位)

  (5)所有叶子节点都在同一层高度

  (6)采用中序遍历

  对于整颗树采用中序遍历,每访问一个节点,就需要访问一次磁盘 IO;对于非叶子节点,节点内的数据采用数组的方式存储,在查询时,把数据从磁盘读取到内存中,再用二分查找,快速找到下一次访问的位置;对于叶子节点,节点内的数据是以单链表存储,叶子节点之间通过前后指针指向构成双向连表,便于范围查找;在查询时,先遍历单链表,再通过双链表找到相邻的叶子节点,继续遍历单链表,依次执行最终找到所查询的数据。

索引

  (1)主键索引

    非空索引,一个表只有一个主键索引,在 innodb 中,主键索引的 B+树包含包含表行数据

    PRIMARY KEY(key)

  (2)唯一索引

    不可以出现相同的索引内容

    UNIQUE(key)

  (3)普通索引

    允许出现相同的索引内容

    INDEX(key) OR KEY(key......)

  (4)组合索引

    对表上的多个列进行索引

    INDEX idx(key1,key2,........)

    UNIQUE(key1,key2,........)

  (5)全文索引

    将存储在数据库当中的整本书和整篇文章中的任意内容信息查找出来的技术;关键词 FULLTEXT;在短字符串中用 LIKE % ;在全文索引中用 match 和 against

C/C++Linux服务器开发高级架构师/C++后台开发架构师​免费学习地址

另外还整理一些 C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以自行添加 qun:点击加入~ 群文件共享,详情看以下视频,详情看以下视频


主键选择的规则

  innodb 中每一张表有且仅有一个主键

    (1)如果设置了 PRIMARY KEY,则该设置的 key 为该表的主键

    (2)如果没有显式设置主键,则从非空唯一索引中选择

      a.只要有非空唯一索引,则选择该索引为主键

      b.有多个非空唯一索引,则选择声明的第一个为主键

    (3)如果没有设置主键,也没有设置非空唯一索引,则自动生成一个 6 字节的_rowid 作为主键

外键约束

  外键用来关联两个表,来保证参照完整性,MyISAM 存储引擎本身不支持外键,innodb 完整支持外键;外键的作用是使表数据实现联动删除/更新,父表删除/更新,子表也会删除/更新。

  约束与索引区别,创建主键或者唯一索引时,同时创建了相应的约束,但是约束是逻辑上的概念,索引是一个数据结构,既包含逻辑也包含物理的存储方式。

索引实现

索引存储

​   innodb 由段、区、页组成:

      (1)段,数据段(每一行数据)、索引段(B+树)、回滚段(事务);每一个段的段空间由区构成(4~5 个区);

      (2)区,区大小为 1MB,每一个区由 64 个连续页构成;

      (3)页,默认值为 16k;页为逻辑页,磁盘物理页大小一般为 4K 或者 8K,为了保证区中的页的连续,存储引擎一般一次从磁盘中申请 4~5 个区;

    页是 innodb 磁盘管理的最小单位,默认 16k,可以通过 innodb_page_size 参数来修改,B+树的一个节点就是一页,大小也就是 16k,以上只是一种组成方式,就类似于内存池由大块、小块组成,并不能确定了一颗 B+树的大小

  聚集索引

    根据主键来构建的 B+树,叶子节点中存放数据页(包含了所有数据),数据也是索引的一部分。

    innodb 当中

    (1)叶子节点中的聚集索引,它的数据和索引也都在叶子节点当中;    (2)数据存储在主键的 B+树。

    myisam 当中

    (1)B+树的叶子节点并不存储数据,而是指针,指针指向数据存储在磁盘位置;

    (2)具体的数据不是存储在 B+树,而是存储在堆表。

    所以 myisam 读取性能高。

    例如:select * from user where id 1 >= 18 and id < 40;在 B+树中查找如下图所示,需要 7 次 IO。

  辅助索引

    即不是根据主键来构建的 B+树。

    辅助索引的叶子节点不包含行记录的全部数据,除了用来排序的键值 key 还包含一个 bookmark,该书签存储了聚集索引的 key。所以,使用辅助所引查找时,如果通过辅助索引不能直接获取到 select 所需的所有字段数据,则先在辅助索引的 B+树中进行查找,找到辅助索引对应的的 key,由于该节点也存储了聚集索引的 key,再到聚集索引的 B+数中找 key 对应的行数据,本次 IO 访问的次数是辅助索引访问次数+聚集索引访问次数;如果通过辅助索引就能获取到查询字段的数据,则不会到聚集索引中查找,此时访问磁盘 IO 次数较少(因为辅助索引 B+树高度一般低于聚集索引 B+树的高度);所以辅助索引可以根据具体的业务场景来创建,进行优化。

    例如: 某个表 包含 id name lockyNum; id 是主键,lockyNum 存储辅助索引;执行 select * from user where lockyNum = 33 流程如下。

最左比配原则

  对于组合索引,从左到右依次匹配,遇到> < between like 就停止匹配。

覆盖索引

  从辅助索引中就能找到数据,而不需要通过聚集索引查找,利用辅助索引树的高度一般低于聚集索引树的高度,较少访问磁盘 IO,当辅助索引中包含索引 key 正好是 select 只要字段,此时不需要访问聚集索引,即可获取。

索引失效

  (1)select ... where A and B 若 A 和 B 中有一个不包含索引,则索引失效;

  (2)索引字段参与了运算,则失效;例如: from_unixtime(idx) = '2021-04-30';

  (3)索引字段发生隐式转换,则失效;例如: '1' 隐式转换为 1;

  (4)LIKE 模糊查询,通配符 %开头,则失效;如果 %在后面是可以的,例如: select * from user where name like '%ark';

  (5)索引字段上使用 NOT <> !=,则失效;例如:判断 id <> 0 则修改为 idx > 0 or idx < 0;

  (6)组合索引中,没使用第一列索引,索引失效。

索引原则

  (1)查询频次较高且数据量大的表建立索引;索引选择使用频次较高,过滤效果好的列或组合;

  (2)使用短索引;节点包含的信息多,较少磁盘 IO 操作(如果索引字段长,B+树相应的高度会高);

  (3)对于很长的动态字符串,考虑使用前缀索引;

  (4)对于组合索引,考虑最左侧匹配原则和覆盖索引;把经常访问的索引放在最左边;

  (5)尽量选择区分度高的列作为索引,该列相同的值越少越好;

  (6)尽量扩展索引,在现有索引的基础上,添加复合索引;在原来的 key 上扩展,而不是新建一个 key;

  (7)不要 select *;尽量只列出需要的列字段;

  (8)索引列,列尽量设置非空,并给一个默认值

EXPLAIN

  用来查看 SQL 语句的具体执行过程

  原理:模拟优化器执行 SQL 查询语句,从而知道 mysql 是如何处理 sql 语句的

SHOW PROCESSLIST

  查看连接线程,可以查看当前连接执行的 sql,以及执行多久;如果要查看完整的 sql 语句,使用 SHOW FULL PROCESSLIST,再进行优化。

原文地址:MYSQL之索引 - MrJuJu - 博客园

用户头像

C/C++后台开发技术交流qun:720209036 2022.05.06 加入

还未添加个人简介

评论

发布
暂无评论
探究MYSQL之索引_MySQL_C++后台开发_InfoQ写作社区