解析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树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]

B+树

B+树是B树的一个变种,B+树比B树更适合实现外存储索引结构,MySQL存储引擎普遍使用B+Tree实现其索引结构。内节点只包含键值以及指向子节点的指针,数据存储在叶子节点,所有记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各节点指针进行连接(双向链表)。
一棵高度为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+树索引可以分为聚集索引(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中主键索引和其它索引在结构上面没有什么不同,主键索引就是一个名为Primary的唯一非空索引。

MyISAM表layout_test的主键分布

MyISAM表layout_test的col2列索引分布

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

InnoDB表layout_test的主键分布

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

InnoDB表layout_test的主键分布

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

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

聚集和非聚集对比图

聚集索引的优点

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

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

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

image

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

聚集索引的缺点

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

参考:

高性能mysql

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

时间: 2024-10-25 22:01:31

解析mysql索引的相关文章

干货篇:一篇文章让你——《深入解析MySQL索引原理 》

概述 最近一段时间重新深入研究了一遍MySQL的内容,今天主要分享分析MySQL索引原理,后续会输出一些关于MySQL方面的干货,希望各位小伙伴喜欢.一.什么是索引.为什么要建立索引? 关于索引的理解,个人更加喜欢将其比喻为字典里面的目录,根据字典来进行查询的速度远大于每一页逐个逐个字排查的速度. 索引主要用于快速找出在某个列中有特定值的行,倘若不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多.如果表中查询的列有一个索引,MySQL能够快

单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式 一 表结构如下:  MySQL  5.5.30  5.6.20 版本, 表大概有815万行 CREATE TABLE t_audit_operate_log (  Fid bigint(16) AUTO_INCREMENT,  Fcreate_time int(10) unsigned NOT NULL DEFAULT '0',  Fuser varchar(50) DEFAULT '',  Fip bigint

Mysql 索引原理(转自:张洋)

摘要 本文以MySQL数据库为 研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据 库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道 的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为三个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库

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

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎 对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索 引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 数据结构及算法基础 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干

浅谈MySQL索引背后的数据结构及算法

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是 平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为四个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库中

MySQL索引及查询优化总结

作者 | 谢庆玲 文章<MySQL查询分析>讲述了使用MySQL慢查询和explain命令来定位mysql性能瓶颈的方法,定位出性能瓶颈的sql语句后,则需要对低效的sql语句进行优化.本文主要讨论MySQL索引原理及常用的sql查询优化. 一个简单的对比测试 前面的案例中,c2c_zwdb.t_file_count表只有一个自增id,FFileName字段未加索引的sql执行情况如下: 在上图中,type=all,key=null,rows=33777.该sql未使用索引,是一个效率非常低的

转:由浅入深探究mysql索引结构原理、性能分析与优化

摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1. 简单介绍B-tree B+ tree树 2. MyisAM索引结构 3. Annode索引结构 4. MyisAM索引与InnoDB索引相比较 第三部分:MYSQL优化 1.表数据类型选择 2.sql语句优化 (1)     最左前缀原则 (1.1)  能正确的利用索引 (1.2)  不能正确的利用索引 (1.3)  如果一个查询where子句中确实不需要password列,那就用“补洞”. (1.4)  like

第10章 mysql 索引

2015-10-24 目录 参考资料 [1] 唐汉明.深入浅出MySQL 数据库开发.优化与管理维护(第2版)[M].北京:人民邮电出版社,2014 [2] Schwartz.高性能MySQL(第3版)[M].北京:电子工业出版社,2013 [3] 范德兰斯.MySQL开发者SQL权威指南 [M].北京:机械工业出版社,2008 [4] Forta.MySQL必知必会 [M].北京:人民邮电出版社,2009 [5] 理解MySQL——索引与优化 [6] mysql索引总结----mysql 索引

[纯干货] MySQL索引背后的数据结构及算法原理

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为三个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库中My