`

mysql索引解析

 
阅读更多

在mysql中,索引存储引擎用于快速查找到目标记录的一种数据结构。常见的索引类型包含B树索引、哈希索引、空间索引(R-Tree)、全文索引等。

索引是在存储引擎层实现的,不同的存储引擎对索引的工作方式并不一样。

下面重点介绍B树索引以及innodb和myisam存储引擎。

选择B树的原因

读写磁盘代价最高的环节是寻道,按照顺序访问范围数据是很快的,这有两个原因:

  1. 顺序I/O不需要多次寻道,所以比随机I/O要快很多(特别是对于机械硬盘)。
  2. 如果服务器能够按需要顺序读取数据,那么就不需要额外的排序操作,并且goup by查询无需再做排序和将行按组进聚合计算了。

索引本身可能很大,不能全部放在内存,因此往往以索引文件的形式存储的磁盘上。这样一来,索引查找过程中就要产生磁盘I/O消耗。相对于内存存取,I/O存取的消耗要高几个数量级,设计索引时,其结构组织要尽量减少查找过程中磁盘I/O的存取次数。

B树是与红黑树类似的一颗平衡查找树,但在降低磁盘I/O操作次数方面更好一些,B树具有较低的深度,查找一个元素只需将很少节点从磁盘Load到内存,很快便能访问到要查找的数据。

B树介绍

B树B树

一棵B树T是具有如下性质的有根树(根为root[T]):

  1. 每个节点x有以下域:
    • x.n,节点x包含的关键字个数。
    • x.n keys本身,以非降序排列,因此
    • x.leaf,布尔值,如果x是叶节点,则为TRUE,若为内节点,则为FALSE
  2. 每个内节点x包含x.n+1个指向其子女的指针,叶节点没有子女,故他们子女的指针域无定义。
  3. 如果ki为存储在节点x子节点内的关键字则:

  4. 每个叶节点具有相同的深度,即树的高度h

  5. 每个节点所包含的关键字个数x.n包含一个上界和下界,用一个固定的整数t>=2来表式;
    • 每个非根的节点至少包含t-1个关键字。每个非根的内节点至少有t个子女,如果树是非空的,则根节点至少包含一个关键字。
    • 每个节点至多包含2t-1个关键字,所以说一个内节点至少包含2t个子女,我们说一个节点是满的,如果这个节点恰好包含2t-1个关键字。

一棵高度为3的B树,它包含最小可能的关键字数,在每个节点x内显示的是n[x]一棵高度为3的B树,它包含最小可能的关键字数,在每个节点x内显示的是n[x]

B+树

B+树是B树的一个变种,B+树比B树更适合实现外存储索引结构,MySQL存储引擎普遍使用B+Tree实现其索引结构。内节点只包含键值以及指向子节点的指针,数据存储在叶子节点,所有记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各节点指针进行连接(双向链表)。

一棵高度为2的B+树一棵高度为2的B+树

如图:所有记录都在叶节点中,井且是顺序存放的,如果我们从最左边的
叶节点开始顺序遍历,可以得到所有镗值的顺序排序15、10、15、20、25、30、50、55、60、 65、 75、 80、 85、 90

B+树内节点和叶节点的大小可以是不同的。

索引实现

存储引擎以不同的方式使用B+树,索引列是按照顺序组织的。B+树索引在数据库中有一个特点就是其高扇出性,因此数据库中B+树的高度一般都在2~3层,也就是说对于查找某一键值的行记录,最多只需要2到3次IO。

建立在B树结构的索引建立在B树结构的索引

B+树索引

数据库中B+树索引可以分为聚集索引(clustered index)和辅助聚集索引(secondary index),但不管是聚集还是非聚集的索引,其内部都是B+树的,即高度平衡的,叶节点存放着所有的数据。

聚集索引与非聚集索引不同的是,叶节点存放的是否是一整行的信息。

来看看InnodDB和MyISAM是如何存储下面这张表的:

1
2
3
4
5
6
Create Table layout_test(
	col1 int not null,
	col2 int not null,
	primary key(col1),
	key(col2) -- 二级索引
)

MyISAM引擎使用B+Tree作为索引结构,索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。叶节点每个项的数据域存放的是记录的地址记录写入时按照插入的顺序存储在磁盘上

MyISAM表layout_test的数据分布MyISAM表layout_test的数据分布

MyISAM中主键索引和其它索引在结构上面没有什么不同,主键索引就是一个名为Primary的唯一非空索引。

MyISAM表layout_test的主键分布MyISAM表layout_test的主键分布

MyISAM表layout_test的col2列索引分布MyISAM表layout_test的col2列索引分布

而在InnoDB中,主键就是聚集索引,表数据文件本身就是按B+Tree组织的一个索引结构,叶子节点包含了主键和行的全部数据,内节点页只包含了索引列主键。聚集索引中键值的逻辑顺序决定了表中相应行的物理顺序。InnoDB二级索引的叶子节点中存储的不是“行指针”,而是主键值,并以此作为指向行的“指针”,可知聚集索引就是按照表的主键构造的一棵B+树。

InnoDB表layout_test的主键分布InnoDB表layout_test的主键分布

聚集索引的叶节点的每一个项包含了主键、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列。

InnoDB表layout_test的主键分布InnoDB表layout_test的主键分布

InnoDB的二级索引和聚集索引很不相同。InnoDB二级索引的叶子节点存储的不是“行指针”,而是主键值,并以此作为指向“行的指针”。这样的策略减少了当前行移动或者数据页分裂时二级索引的维护工作。使用主键值当做索引指针会让二级索引占用更多的空间,换来的好处是,InnoDB在移动时无需更新二级索引中的这个“指针”。

从下图比较容易看出InnoDB和MyISAM保存数据和索引的区别。

聚集和非聚集对比图聚集和非聚集对比图

聚集索引的优点

聚集索引的存储井不是物理上的连续,相反是逻辑上连续的,页内是连续的,页间通过双向链表链接。

聚集索引的另一十好处是,它对于主键的排序查找和范国查找速度非常快。

innodb的逻辑存储结构, 从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称为(block),InnoDB存储引擎的逻辑存储结构大致如图:

imageimage

  • 可以把相关数据保存在一起,尤其是访问的数据聚集在一个页上,可以减少io次数;
  • 数据访问更快。聚族索引将索引和数据保存在同一个B树中,因此从聚族索引中获取数据通常比在非聚族索引中查找更快。
  • 使用覆盖索引扫描的查询可以直接使用节点中的主键值。

聚集索引的缺点

  • 聚集数据最大限度的提高了I/O密集型应用的性能,但如果数据全部都放在内存中,则访问的顺序就没有那么重要了,聚集索引也就没有那么优势了;
  • 插入速度严重依赖于插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。但如果不是按照主键顺序加载数据,那么在加载完成后最好使用OPTIMIZE TABLE命令重新组织一下表。
  • 更新聚集索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置。
  • 基于聚集索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临“页分裂”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次分裂操作。页分裂会导致表占用更多的磁盘空间。
  • 聚集索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
  • 二级索引(非聚集索引)可能比想象的要更大,因为在二级索引的叶子节点包含了引用行的主键列。
  • 二级索引访问需要两次索引查找,而不是一次。

参考:

高性能mysql

MySQL索引背后的数据结构及算法原理

分享到:
评论

相关推荐

    MySql索引算法原理解析(通俗易懂,只讲B-tree)

    NULL 博文链接:https://zzc1684.iteye.com/blog/2226223

    MySQL索引机制(详细+原理+解析).doc

    MySQL 索引机制详细解析 MySQL 索引机制是 MySQL 中的一种数据结构,它可以加快数据的检索速度。索引机制是指在数据库中的每一列上建立的数据结构,是一种快速查找和定位数据的方法。 一、索引的类型 MySQL 索引...

    mysql索引原理深入解析

    不生产资源,只是资源的搬运工,如有侵权,请及时联系,谢谢! 目录: 一、 索引是什么? 二、 索引存储模型推演 三. B+Tree 落地形式 四、 索引使用原则 五. 索引的创建与使用

    MySQL索引长度限制原理解析

    这篇文章主要介绍了MySQL索引长度限制原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 索引 TextField是不支持建立索引的 MySQL对索引字段长度有限制 ...

    MySql索引算法原理解析

    而B+tree是B-tree的一个变种,大名鼎鼎的MySQL就普遍使用B+tree实现其索引结构。那数据库为什么使用这种结构?一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样...

    简单谈谈Mysql索引与redis跳表

    面试时,交流有关mysql索引问题时,发现有些人能够涛涛不绝的说出B+树和B树,平衡二叉树的区别,却说不出B+树和hash索引的区别。这种一看就知道是死记硬背,没有理解索引的本质。本文旨在剖析这背后的原理,欢迎留言...

    CcoWzh#Interview-Of-Programmer#MySQL索引原理1

    MySQL索引原理查找算法:二叉查找树BitMap位图索引分类主键索引唯一索引普通索引全文索引索引原理解析B+树聚集索引和非聚集索引建立索引创建表时指定组合索引

    MySQL进阶学习需要掌握的具体内容解析,MySQL数据库如何使用和优化索引.docx

    索引是MySQL中一个重要的概念,它可以显著提高查询性能。因此,在设计和使用MySQL数据库时,了解如何使用和优化索引非常重要。 一个索引是一种数据结构,可以快速定位和访问表中的数据。MySQL支持多种类型的索引,...

    MySQL hint用法解析

    我们可以对MySQL的对象(表、索引、触发器、自建函数、存储过程等)做注释(comment),这样做的目的是标识该对象的作用等以增强代码的可读性、方便其他同事快速读懂我们写的代码或某个数据库对象的作用,说白了,...

    Mysql使用索引的正确方法及索引原理详解

    主要给大家介绍了关于Mysql使用索引的正确方法及索引原理的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用mysql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    关于MySQL索引的深入解析

    前言 我们知道,索引的选择是优化器阶段的工作,但是优化器...mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1; +----+-------------+-------+--

    Java高级编程——MySQL索引实现及优化原理解析

    在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。MyISAM索引实现MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的...

    MySQL训练营视频.zip

    │ day2_MySQL索引深入剖析-笔记.pdf │ day2_MySQL索引深入剖析-课件.mp4 │ day2_MySQL索引深入剖析-课件.pdf │ day3_MySQL事务与锁详解-笔记.pdf │ day3_MySQL事务与锁详解-课件.pdf │ day3_MySQL事务与锁详解...

    MySQL面试全面解析手册

    MySQL面试全面解析手册是一本专为MySQL开发和面试准备而设计的综合性资源。该手册详细介绍了MySQL数据库的基本概念、SQL语法、常见查询优化技巧以及高级主题如索引优化、事务处理和复制等。通过系统化的知识点总结、...

    MySQL数据库经典面试题解析

    1. MySQL 索引使用有哪些注意事项呢? 可以从三个维度回答这个问题:索引哪些情况会失效,索引不适合哪些场景,索引规则 索引哪些情况会失效 查询条件包含or,可能导致索引失效 如何字段类型是字符串,where时一定...

    mysql面试题100题,包含答案和解析.docx

    mysql面试题,包含总共100题,并且附带详细答案和解析,部分面试题如下: 1、MySQL 索引使用有哪些注意事项呢? 2、MySQL 遇到过死锁问题吗,你是如何解决的? 3、日常工作中你是怎么优化SQL的? 4、InnoDB与MyISAM...

    【mysql面试题】100道MySQL数据库经典面试题解析

    1. MySQL索引使用有哪些注意事项呢? 可以从三个维度回答这个问题:索引哪些情况会失效,索引不适合哪些场景,索引规则 索引哪些情况会失效  查询条件包含or,可能导致索引失效   如何字段类型是字符串,where...

    运用解析器优化MySQL数据库查询性能.pdf

    摘要: 本文首先阐述了索引在数据库查询优化中的重要作用,然后详细介绍了在MySQL中如何利用各种索引技术来帮助查询优化器生成更高效的执行计划,以提升查询性能,...关键词:MySQL,数据库,查询优化,索引,执行计划,解析器

Global site tag (gtag.js) - Google Analytics