> 文档中心 > Mysql高性能索引

Mysql高性能索引

你有没有想过,为什么数据库查询时速度这么快?其实,这背后离不开索引这个“幕后英雄”。索引就像是图书馆的目录,帮你快速找到想要的书(数据)。但索引的实现原理可不是那么简单,它有B-Tree、B+Tree、Hash等多种底层结构。B+Tree之所以成为主流,主要是因为它在查找大量数据时,IO次数少,效率高。比如,3层B+Tree就能搞定上百万条数据,只需3次IO,这比没有索引时的百万次IO快多了!

那么问题来了,为什么有时Mysql会“选错索引”呢?这就涉及到查询优化器的“小脾气”了。优化器会根据统计信息来选择索引,但如果统计信息不准确,或者查询条件复杂,它可能会误判。比如,你明明觉得用索引A更快,但优化器偏偏选了索引B,结果查询效率反而变慢了。这时,你可以通过强制指定索引或更新统计信息来“纠正”优化器的错误。

再来聊聊InnoDB和MyIsam的索引区别。InnoDB的索引是“聚簇索引”,数据和索引是绑在一起的,而MyIsam的索引只是指向数据的指针。简单概括,InnoDB的索引更像“内容目录”,而MyIsam的索引则是“页码目录”。所以,InnoDB在数据查找时更高效,但MyIsam在插入和删除时更快。你可能会问,那我该用哪个?这得看你的业务场景,是查询多还是更新多。

最后,唯一索引和普通索引的区别也很值得探讨。唯一索引保证了数据的唯一性,但它的插入速度可能会慢一点,因为要检查唯一性。普通索引则没有这个限制,插入更快,但可能会带来重复数据。所以,选择哪种索引,取决于你是更看重数据的唯一性,还是更看重性能。总之,索引的世界很大,了解它的原理和应用场景,才能让数据库跑得更快!

一、索引是什么 

二、索引的底层实现原理

三、InnoDB的存储结构是怎样的? 

四、InnoDB索引和MyIsam索引对比 

 五、Mysql为什么会选错索引

六、唯一索引和普通索引的区别


导读:本博文讲解了索引是什么和索引的底层原理,提到了 BTREE和 B+TREE hash底层实现以及mysql选错索引的原因和解决方式。同时涵盖高频面试题之InnoDB索引和MyIsam索引对比区别,唯一索引和普通索引的区别。

一、索引是什么 

索引的概念:索引是一种特殊的文件,它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度

索引的作用:索引的目的在于提高查询效率,使原始的随机全表扫描变成快速顺序锁定数据

常用索引的分类:
普通索引:这是最基本的索引,它没有任何限制
唯一索引:引列的值必须唯一,但允许有空值(注意和主键不同)
组合索引:多个数据列组成的索引,遵守最左匹配原则

索引高性能保证:
    把查询过程中的随机事件变成顺序事件
    数据保存在磁盘上,而为了提高性能,每次又可以把部分数据读入内存来计算,访问磁盘的成本大概是访问内存的十万倍左右

磁盘IO与预读:
        考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k

二、索引的底层实现原理

hash索引 无法满足范围查找,优点:等值检索快,范围检索很慢,因为hash值是不连续的

B-TREE 每个节点都是一个二元数组: [key, data],所有节点都可以存储数据。key为索引key,data为除key之外的数据

 B-TREE的缺点:插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质。造成IO操作频繁。区间查找可能需要返回上层节点重复遍历,IO操作繁琐

B+Tree的改进:非叶子节点不存储data,只存储索引key;只有叶子节点才存储data

B+树高性能保证:

        3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高
在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree
B+TREE 只在叶子节点存储数据 & 所有叶子结点包含一个链指针 & 其他内层非叶子节点只存储索引数据。只利用索引快速定位数据索引范围,先定位索引再通过索引高效快速定位数据。

三、InnoDB的存储结构是怎样的? 

InnoDB物理存储结构分析

InnoDB以表空间Tablespace(idb文件)结构进行组织,每个Tablespace 包含多个Segment段,每个段(分为2种段:叶子节点Segment&非叶子节点Segment), 一个Segment段包含多个Extent,一个Extent占用1M空间包含64个Page(每个Page 16k),InnoDB B+Tree 一个逻辑节点就分配一个物理Page,一个节点一次IO操作。,一个Page里包含很多有序数据Row行数据,Row行数据中包含Filed属性数据等信息

 索引值匹配检索过程:确定定位条件, 找到根节点Page No, 根节点读到内存, 逐层向下查找, 读取叶子节点Page,通过 二分查找找到记录或未命中。(select * from user_info where id = 23) 

索引范围查找:读取根节点至内存, 确定索引定位条件id=18, 找到满足条件第一个叶节点, 顺序扫描所有结果, 直到终止条件满足id >=21 (select * from user_info where id >= 16 and id < 21)

 全表扫描:直接读取叶节点头结点, 顺序扫描, 返回符合条件记录, 到最终节点结束(select * from user_info where user_name = 'daniel')

四、InnoDB索引和MyIsam索引对比 

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址,MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复

InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引
第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域

MyIsam叶子data域放的是指针

InnoDB 主键索引,又是聚簇索引 (就是数据 和索引放在一起,我们称之为聚簇索引,性能最高)

 InnoDB非主键索引,非聚簇索引 data中存储的是id