mysql索引数据结构详解---mysql详解(一)

文章目录

  • 磁盘存取原理
  • 数据结构
    • 二叉树:
    • 红黑树:
    • B-TREE:
    • B+TREE
    • B-TREE数据存储方式:
    • mysql的B+TREE数据存储方式
    • mysql存储引擎
      • MyISAM
      • InnoDB
  • 联合索引的底层数据结构
      • 字符串类型
      • 多种数据类型组成的联合索引
    • 联合索引使用情况
  • 划重点(∩_∩)

磁盘存取原理

mysql的数据最终是在磁盘的,读取数据也是从磁盘读取。
那么就有必要知道磁盘的工作原理。
如图所示磁盘的结构图。
磁盘是逆时针旋转的,而磁头只能左右移动。磁头通过左右移动来划定磁道,从磁道中获取数据,数据存储在各个磁道的扇区中。

如果一个数据表中的数据,存储在不同的磁道中,那么就需要多次寻道,耗时就会长。

mysql索引数据结构详解---mysql详解(一)_第1张图片

数据结构

非常直观,很好用。
数据结构动态演示网站
mysql为什么采取BTREE、HASH的数据结构?而没有采取二叉树、红黑树的数据结构。可以去这样网站试一下上述数据结构就清楚了。
因为二叉树、红黑树当数据量大时,都会导致数据深度太大。
Hash我们也很少用,因为hash对范围查询不友好。
BTREE的优点是的mysql的索引基本都是用BTREE。不过mysql的底层用的是B+TREE,比BTREE更高效。

BTREE的度(Degree)-节点的数据存储个数。存储个数不能无限大,因为磁盘每次读取数据是有限的,比如磁盘每次读取20kb的数据,而节点存储了10M的数据,那么就需要读取10M/20kb次。一样会导致效率极低。
磁盘一页是4kb大小,而i你如果能保证每个B+TREE的节点是4kb大小。这样就提高了效率。

二叉树:

mysql索引数据结构详解---mysql详解(一)_第2张图片

红黑树:

mysql索引数据结构详解---mysql详解(一)_第3张图片

B-TREE:

mysql索引数据结构详解---mysql详解(一)_第4张图片
我们提到的查询磁盘存取原理,我们找磁盘其实是找节点,节点数据会读取到内存,内存再读取,内存的速度可以忽略不计。所以BTREE我们查询0004的话,就是把包含0002、0004的节点读取到内存。

B+TREE

mysql索引数据结构详解---mysql详解(一)_第5张图片

B-TREE数据存储方式:

mysql索引数据结构详解---mysql详解(一)_第6张图片

mysql的B+TREE数据存储方式

mysql索引数据结构详解---mysql详解(一)_第7张图片
B+TREE的指针更方便mysql进行范围查询。
B+Tree索引的性能分析:

  • 一 般 使 用 磁 盘 I/ O次 数 评 价 索 引 结 构 的 优 劣
  • 预 读 : 磁 盘 一 般 会 顺 序 向 后 读 取 一 定 长度的数据(页的整数倍)放入内存
  • 局 部 性 原 理 : 当 一 个 数 据 坫 用 到 时 , 其 附 近 的 数 据 也 通 常 会 马 上 被 使 用
  • B+ Tree节 点 的 大小 设 为 等 于 一 个 页 , 每 次 新 建 节 点 直 接 中 访 一 个 页 的 空 间 , 这 样 就 保 证 一 个 节 点 物理上也 存 储 在 一 个 页 里 , 就 实 现了一 个 节 点 的 载入只需一 次 I/O
  • B+ Tree的 度 d—般会超过100,因此h非常小(一般为3到5之间)

mysql存储引擎

MyISAM和InnoDB。这两个存储引擎都是表级别的。

MyISAM

MyISAM存储引擎存储方式:
mysql索引数据结构详解---mysql详解(一)_第8张图片
实际上MyISAM的B+TREE不存储data,而是存储data的指针。
MyISAM的主键索引和非主键索引一样。
题外:如果用UUID作为表的主键,方便数据库做迁移。

InnoDB

mysql索引数据结构详解---mysql详解(一)_第9张图片
实际上InnoDB的B+TREE存储了data
InnoDB的主键索引和非主键索引不一样。

联合索引的底层数据结构

字符串类型

如title、name两个字段均为字符串类型组成联合索引,那么联合索引的就是title+name这样加起来作为一个字符串索引。

多种数据类型组成的联合索引

如图所示:第一个为int类型,第二个为varchar,第三个为date。
mysql索引数据结构详解---mysql详解(一)_第10张图片
那么联合索引会先用第一索引去比较,第一索引相同再用第二索引比较,第二索引相同再用第三索引去比较。

联合索引使用情况

注意: mysql的单个索引是联合索引的特殊情况

create table test(
a int ,
b int,
c int,
d int,
key index_abc(a,b,c)
)engine=InnoDB default charset=utf8;

查询语句

EXPLAIN
SELECT *
FROM `test` WHERE a='a';--  true
EXPLAIN
SELECT *
FROM `test` WHERE b='b'; -- false
EXPLAIN
SELECT *
FROM `test` WHERE c='c'; -- false
EXPLAIN
  SELECT *
  FROM `test` WHERE a='a' AND b='b'; --  true
EXPLAIN
    SELECT *
    FROM `test` WHERE b='b'  AND a='a';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE a='a'  AND c='c';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE c='c'  AND a='a';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE c='c'  AND b='b';--  false
EXPLAIN
    SELECT *
    FROM `test` WHERE b='b'  AND c='c';--  false
EXPLAIN
    SELECT *
    FROM `test` WHERE a='a'  AND b='b' AND c='c';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE a='a'  AND c='c' AND b='b';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE b='b'  AND c='c' AND a='a';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE b='b'  AND a='a' AND c='c';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE c='c'  AND b='b' AND a='a';--  true
EXPLAIN
    SELECT *
    FROM `test` WHERE c='c'  AND a='a' AND b='b';--  true
EXPLAIN
	select * from test where b<10 and c <10;-- false
EXPLAIN 
	select * from test where a<10 and c <10;-- ture

mysql查询优化器会判断纠正这条sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。所以,当然是我们能尽量的利用到索引时的查询顺序效率最高,所以mysql查询优化器会最终以这种顺序进行查询执行。
所以当a字段不在最左时,mysql会自动调整到最左的位置然后再执行。
而根据联合索引数据结构图也可以看出,必须有a字段,联合索引才会生效。

另外的例子:
mysql索引数据结构详解---mysql详解(一)_第11张图片

划重点(∩_∩)



本人程序媛一枚,因为离港澳较近,周末兼职港澳人肉代购。

欢迎各位大佬添加本人微信,还会经常有点赞活动送价值不菲的小礼品哦。

即使现在不需要代购,等以后有了女(男)朋友、有了宝宝就肯定会需要的喽。

动动手指头,扫码一下,就当是对本博文的支持嘛,也是对一个平凡、勤劳、勇敢、秀外慧中等等优点的程序媛莫大的支持哈。

你可能感兴趣的:(数据库)