在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索引背后的数据结构及算法原理

解析mysql索引的更多相关文章

  1. 你真的理解索引吗?从数据结构层面解析mysql索引原理

    从<mysql存储引擎InnoDB详解,从底层看清InnoDB数据结构>中,我们已经知道了数据页内各个记录是按主键正序排列并组成了一个单向链表的,并且各个数据页之间形成了双向链表.在数据页 ...

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

    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式     一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid b ...

  3. Mysql索引使用解析

    摘自:http://blog.chinaunix.net/uid-25063573-id-3032578.html Mysql索引使用解析 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库 ...

  4. 【详细解析】MySQL索引详解( 索引概念、6大索引类型、key 和 index 的区别、其他索引方式)

    [详细解析]MySQL索引详解( 索引概念.6大索引类型.key 和 index 的区别.其他索引方式) MySQL索引的概念: 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分 ...

  5. mysql索引原理深度解析

    mysql索引原理深度解析 一.总结 一句话总结: mysql索引是b+树,因为b+树在范围查找.节点查找等方面优化 hash索引,完全平衡二叉树,b树等 1.数据库中最常见的慢查询优化方式是什么? ...

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

    MySQL索引机制 永远年轻,永远热泪盈眶 一.索引的类型与常见的操作 前缀索引 MySQL 前缀索引能有效减小索引文件的大小,提高索引的速度.但是前缀索引也有它的坏处:MySQL 不能在 ORDER ...

  7. MYSQL索引结构原理、性能分析与优化

    [转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...

  8. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  9. [转]MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

随机推荐

  1. FindBugs Bug Descriptions

    FindBugs Bug Descriptions ◇例1: Integer a = ; String str ="; System.out.println(str == a.toStrin ...

  2. 【Spark学习】Apache Spark监控与测量

    Spark版本:1.1.1 本文系从官方文档翻译而来,转载请尊重译者的工作,注明以下链接: http://www.cnblogs.com/zhangningbo/p/4137952.html

  3. Codeforces Educational Codeforces Round 15 A. Maximum Increase

    A. Maximum Increase time limit per test 1 second memory limit per test 256 megabytes input standard ...

  4. 【bzoj3233】【ahoi2013】找硬币

    题意: 求确定n种货币面额x1..xn满足 x1=1 且xi为xj的整数倍(i>j) 给定n个物品价格ai 求使用上面货币最少需要硬币数(不能找零) 题解: 动态规划 听说网上的题解都是搜索的做 ...

  5. 第二百九十三天 how can I 坚持

    总感觉怪怪的,换了个领导,好烦,虽然对我没用影响. 其实,还是智商低,不懂人情世故,就像...算了,不说了,只能当自己傻. 最近好冷啊,十年不遇的寒冬. 心情有些压抑. 不玩游戏了,看了集康熙来了.小 ...

  6. 【转】Nginx系列(四)--工作原理

    原博文出于:    http://blog.csdn.net/liutengteng130/article/details/46724081  感谢! 上篇文章介绍了Nginx框架的设计之管理进程以及 ...

  7. 【现代程序设计】【期末作业】【homework-09】

    作业要求说明: http://www.cnblogs.com/xinz/p/3441537.html 我在做一个什么样的应用: 展示如何逐步求解一个加权矩阵的 最大子矩阵 任意联通图形 下面是软件的截 ...

  8. Oracle 递归查询

    现实中我们经常需要用到一些递归查询,下面我们来介绍下ORACLE中递归查询的使用. 首先我们先新建一个表来存储以上信息 create table FAMILY ( person_id INTEGER, ...

  9. jQuery基础学习7——层次选择器find()方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. Umbraco Forms 中的Recaptcha遇到的问题

    在Umbraco Form中添加Recaptcha时,不能把它设置成Mandatory, 否则就会出错