Mysql-01深入理解Mysql索引底层数据结构与算法

文章重点

索引的本质

索引数据结构

INNODB和MYISAM

聚簇索引和非聚簇索引

联合索引

索引是什么?

        索引是帮助MySQL高效获取数据的排好序的数据结构

        数据在磁盘上随机分布,用索引检索数据时能减少磁盘IO次数

索引数据结构

  • 二叉树,红黑树,B树,Hash表,B+树

二叉树

        用递增列创建索引,二叉树退化成链表

Mysql-01深入理解Mysql索引底层数据结构与算法_第1张图片Mysql-01深入理解Mysql索引底层数据结构与算法_第2张图片

红黑树

        是一种近似平衡的二叉搜索树,能够保证任何一个节点的左右子树的高度差小于两倍

        数据量大时,树的高度会很大,从根节点检索效率低

Mysql-01深入理解Mysql索引底层数据结构与算法_第3张图片

B树

        一个节点放多个元素(对应到磁盘上一块连续的区域),所以树高度不会太大

        节点存储key和指向数据的地址data

        叶节点具有相同的深度,叶节点的指针为空

        所有索引元素不重复

        节点中的数据索引从左到右递增排列

        高度:预估每个key+data≈1kb, 一个节点大约16个元素

                  2000万行数据表,16的n次方≈2000万,则n就是树的高度(较B+树高度会更大)

Mysql-01深入理解Mysql索引底层数据结构与算法_第4张图片

Mysql-01深入理解Mysql索引底层数据结构与算法_第5张图片

Hash表

        对索引的key进行一次hash计算就可以定位出数据存储的位置

        hash冲突问题,先根据key进行hash运算定位到位置,再遍历位置上的链表

        仅能满足“=”,“IN",不支持范围查询(hash后数据变的无序)

Mysql-01深入理解Mysql索引底层数据结构与算法_第6张图片

B+树

        叶子节点包含所有元素,冗余存储非叶子节点,叶子节点存储key和data

        非叶子节点只存key(可以存更多元素)

        一个节点对应一个Innodb页=16kb     

        根节点常驻内存,也可以把非叶子节点都放到内存

        叶子节点之间有双向指针,区间查找性能高

        高度:假设字段类型是bigint8字节,指向下一层节点的指针6字节,16kb/14字节≈1170

                   叶子节点上一个key+data≈1kb,叶子节点大约16个元素

                   一颗3层的B+树可以存储1170*1170*16≈2000万行数据

Mysql-01深入理解Mysql索引底层数据结构与算法_第7张图片

Mysql-01深入理解Mysql索引底层数据结构与算法_第8张图片

InnoDB 和 MyISAM

MYISAM存储引擎表

table_a包括 table_a.frm表结构文件、 table_a.MYD表数据文件、 table_a.MYI索引文件

INNODB存储引擎表

table_b包括table_b.frm表结构文件 、table_b.idb表数据文件(索引和数据位于一个文件)

聚簇索引

INNODB存储引擎表的主键索引,每个表只有一个聚簇索引

表数据文件本身就是按B+Tree组织的一个索引结构文件

叶节点包含了完整的数据记录

Mysql-01深入理解Mysql索引底层数据结构与算法_第9张图片

非聚簇索引

INNODB存储引擎表的非主键索引,叶子节点key为索引值,data为主键值

INNODB根据非主键索引查询时可能需要回表查询主键索引

Mysql-01深入理解Mysql索引底层数据结构与算法_第10张图片

MYISAM存储引擎的主键索引和非主键索引,叶子节点key为主键/非主键,data为指向磁盘数据的指针

MYISAM根据索引查询时涉及到跨文件,先检索.MYI文件,然后到.MYD拿数据,效率低

Mysql-01深入理解Mysql索引底层数据结构与算法_第11张图片

为什么建议InnoDB表必须建主键

INNODB表一定有主键,没有设置自增主键,选择第一个含唯一索引的列作为主键,如果没有含唯一索引的列则使用隐藏的行rowid作为主键,组织整张表的数据。

并且推荐使用整型的自增主键?

整形自增主键占用空间小,方便比大小

非自增涉及树的分裂、平衡,而自增节点满了则建一个新的节点,效率更高

为什么非主键索引叶子节点存储的是主键值?

节省存储空间,不需要非主键索引维护全量数据,非主键索引叶子节点只存储主键的值

如果非主键索引的叶子节点存储具体的数据,那么在查询时需要同时存在两份数据,这会导致数据的不一致。因此,非主键索引的叶子节点存储主键值,可以避免多份数据导致的不一致性问题。根据非主键索引查询时拿不到的数据回表去主键索引获取。

联合索引

索引结构

使用employees其中三个字段name,age,hobby建立联合索引

构建索引树时上层的节点通常由下层节点中最左边的元素组成

先按照name排序,name相同时再按照age排序,name和age都相同再按照hobby排序

Mysql-01深入理解Mysql索引底层数据结构与算法_第12张图片

最左前缀原则

KEY `idx_name_age_hobby` (name,age,hobby) USING BTREE

①EXPLAIN select * from employees where name='bill' and age=3;

②EXPLAIN select * from employees where age=30 and hobby='dev'; 

③EXPLAIN select * from employees where hobby = 'manager';

先按照name排序,name相同时再按照age排序,name和age都相同再按照hobby排序

语句②和③不能使用索引,因为没有name条件,age是无序的,需要全表扫描

跳过name和age条件,hobby也是无序的

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