广告
返回顶部
首页 > 资讯 > 数据库 >MySQL索引原理
  • 618
分享到

MySQL索引原理

MySQL索引原理 2020-02-14 06:02:17 618人浏览 才女
摘要

定义 索引(Index)是帮助Mysql高效获取数据的数据结构。那么什么数据结构可以用来高效的获取数据呢? 查看索引 mysql> show index from user; +-------+------------+----------

MySQL索引原理

定义

索引(Index)是帮助Mysql高效获取数据的数据结构。那么什么数据结构可以用来高效的获取数据呢?

查看索引

mysql> show index from user;
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name         | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY          |            1 | id          | A         |           5 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | idx_name_address |            1 | name        | A         |           5 | NULL     | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_name_address |            2 | address     | A         |           5 | NULL     | NULL   | YES  | BTREE      |         |               |
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set

各列的含义:

  • Table:索引所在的表名。
  • Non_unique:非唯一的索引,可以看到primary key是0,因为必须是唯一的。
  • Key_name:索引的名字,用户可以通过这个名字来执行DROP INDEX。
  • Seq_in_index:索引中该列的位置,如果看联合索引idx_name_address就比较直观了。
  • Column_name:索引列的名称。
  • Cardinality:非常关键的值,表示索引中唯一值的数目的估计值。Cardinality/表的行数(Cardinality/n_rows_in_table)应尽可能接近1,如果非常小,那么用户需要考虑是否可以删除此索引。
  • Sub_part:是否是列的部分被索引。如果看idx_b这个索引,这里显示100,表示只对b列的前100字符进行索引。如果索引整个列,则该字段为NULL。
  • Packed:关键字如何被压缩。如果没有被压缩,则为NULL。
  • Null:是否索引的列含有NULL值。可以看到idx_b这里为Yes,因为定义的列b允许NULL值。
  • Index_type:索引的类型。InnoDB存储引擎只支持B+树索引,所以这里显示的都是BTREE。
  • Comment:注释。

数据结构

我们平常见到的检索效率比较高的数据结构有二叉树,平衡二叉树等。

二叉树

二叉树的特性

左子树的键值总是小于根的键值,右子树的键值总是大于根的键值。

image.png

如图如果我们查询8只需要查找3次就行了,但是二叉树可以任意构造,同样是2、3、5、6、7、8也可以构造成如下:

image.png

这时我们同样是查询8这个节点,我们需要查询5次,查询效率就比较低了。

平衡二叉树

因为二叉树存在构造方式的不同会导致查询效率比较低的情况,所以后来又提出了平衡二叉树。

平衡二叉树的特性

首先符合二叉查找树的定义,其次必须满足任何节点的两个子树的高度最大差为1。

avltree.gif

上图是一个平衡二叉树的动态示例,通过示例我们可以发现,为了保证二叉树的平衡我们需要对树进行一定的转换操作。但是为什么没用平衡二叉树来做索引呢?下面我们来看下查找元素9的过程:

find_avltree.gif

如果红圈每移动一次就代表一次IO操作的话,那么查找元素9就需要3次I/O,而在我们计算机系统里面,IO成本是远高于内存中查找的过程。

我们从磁盘读取数据大致可以分为三步:寻道、旋转延迟和数据传输:

  • 寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下。
  • 旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转/分,那么他的平均旋转延迟就是60*1000/7200/2 = 4.17ms
  • 传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计。

根据上面的计算方式,刚刚查找9这个数值,就IO需要花费27ms,现在才7个数据,要是数据量一大,树的高度就会很高,就IO所花费的时间我们就无法接受。

B-Tree

为了降低树的高度,进而减少IO操作,于是又在平衡二叉树上有进行了演化,设计出了B树。

image.png

B-Tree特性

  1. d>=2,即B-Tree的度,也就是每个树节点可以存放数据节点的个数;
  2. h为B-Tree的高,所有叶子节点的树高要相同;
  3. 每个非叶子结点由n-1个key和n个指针组成,其中d<=n<=2d,一个树节点的结构示例[(指针)(数据)(指针)]
  4. 每个叶子结点至少包含一个key和两个指针,最多包含2d-1个key和2d个指针,叶结点的指针均为NULL; key和指针相互间隔,结点两端是指针;
  5. 一个树节点中,数据节点更加key排序,从左至右依次减递减;
  6. 一个数据点A,左指针对应树节点为B,右边指针对应节点为C,那么B中所有数据节点的key小于或等于A,C中所有数据节点的key大于A。
  7. 在一个数据节点中存放了一条完整的数据,即数据库中一条完整的数据记录。

B-Tree的动态演示

这是一颗最大度是3的B树,依次插入数据1,2,3,4,5,6 效果如下:

btree.gif

B-Tree的缺点

  1. 每个数据节点都包含了完整的数据,导致一个树节点中所存放的数据节点变少,最终会导致,树的高度增加。
  2. 不适合范围查找

B+Tree

为了进一步减小数的高度,在B-Tree的基础上演化而来了B+Tree:

image.png

B+Tree特性

  1. 只有最后一层树叶子节点中的数据节点才会存放完整的数据,这样的好处是:树高小于h的树节点可以存放更多的key。
  2. 在最后一层的树叶子节点之间加上了指针,树节点之间构成了一个双向链表,这样做的好处是:可以在最后一层树节点上进行范围查询。
  3. 最后一层树节点包含了所有数据节点,也就是说一个B+Tree的树,他的数据节点在整棵树中可能会重复存储。
  4. 为了提升查询速速,树高小于h的树节点,并不会存放所有的key,他只会存放一些中位数据节点的key。

B+树的插入操作

image.png

B+Tree插入的动态演示,这是一颗最大度是3的B树,依次插入数据1,2,3,4,5,6 效果如下:

bplustree.gif

从图中我们可以看到在插入元素5的时候发生了拆分,拆分就意味着树的高度有可能会增加,为了尽量减拆分,B+树同样提供了类似于平衡二叉树的旋转(Rotation)功能。旋转发生在Leaf Page已经满,但是其的左右兄弟节点没有满的情况下。这时B+树并不会急于去做拆分页的操作,而是将记录移到所在页的兄弟节点上,如插入5,最后的结果是如下图:

image.png

B+树的删除操作

image.png

索引的设计

通过上面的介绍我们可以发现,数据结构不停的演化主要还是在降低查询数据时I/O的次数,那B+Tree的树节点到底多大合适呢,mysql默认树节点的大小是16K,通过如下命令可以查询:

mysql> show variables like "innodb_page_size";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set

磁盘预读

页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页,每页大小通常为4k,主存和磁盘以页为单位交换数据。而为了尽量减少I/O,磁盘往往不是严格按照需求读取数据,而是每次都会预读,预读发生在物理上连续的空间上,预读的大小一般是页的整倍数。

基于预读原理,Mysql索引的树节点大小也也设计为页的整倍数,即4K的整倍数,考虑到磁盘的预读,所以MySQL默认的树节点大小为4页即16K。

为啥不设置的更大一点呢?从上面我们结构图我们可以发现,并不是所有的树节点都能装满,如果出现未装满的情况就会发生空间浪费;还有就是磁盘预读页数还是有限制的,不会无限读取后面的数据,否则就不叫预读了。

聚集索引

将数据文件和索引文件一起存放的索引就是聚集索引,否则是非聚集索引。

InnoDB会按照主键构造一颗B+树,并且在叶子节点存放一行记录的完整数据,所以InnoDB的主键索引就是一个聚集索引。

一张表只能有一个主键,所以也只能有一个聚集索引。在大多数情况下优化器会选择使用聚集索引,因为使用聚集索引可以直接找到数据。

聚集索引的存储并不是物理上连续的,而是逻辑上连续的。这其中有两点:一是前面说过的页通过双向链表链接,页按照主键的顺序排序;另一点是每个页中的记录也是通过双向链表进行维护的,物理存储上可以同样不按照主键存储。

非聚集索引

非聚集索引也称为辅助索引,叶子节点并不存放完整的数据,而是存放key和一个书签(bookmark)。该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据。

当通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录。例如,在一棵高度为3的辅助索引树中查找数据,那需要对这棵辅助索引树遍历3次找到指定主键,如果聚集索引树的高度同样为3,那么还需要对聚集索引树进行3次查找,最终找到一个完整的行数据所在的页,因此一共需要6次逻辑IO访问以得到最终的一个数据页。

image.png

通过上面介绍我们可以发现,当使用辅助索引的时候可能会出现离散读的情况,但是一般的数据库都通过实现预读(read ahead)技术来避免多次的离散读操作。

联合索引

联合索引其实就是用多个列创建的索引,如:

CREATE TABLE t (
	a INT,
	b INT,
	PRIMARY KEY (a),
	KEY idx_a_b (a, b)
) ENGINE = INNODB;

联合索引也是一棵B+Tree,不同的是联合索引的键值的数量不是1,而是大于等于2,如图:

image.png

叶子节点是按照(a,b)进行排序后的存储的,所以当我们执行SELECT * FROM TABLE WHERE a=xxx and b=xxx或者SELECT * FROM TABLE WHERE a=xxx是可以使用索引的,因为最前面a这个字段在索引idx_a_b 上是有序的;但是SELECT * FROM TABLE WHERE b=xxx是不可以使用到索引的,主要是因为b在idx_a_b 索引上是无序的,会产生离散读。

覆盖索引

覆盖索引就是从辅助索引中就可以得到查询的记录。

使用覆盖索引的一个好处是:

  1. 辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引。
  2. 能直接在索引上就可获得全部数据,因此可以减少大量的IO操作。

Multi-Range Read优化

Multi-Range Read优化的目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问。

MRR的工作方式

  1. 将查询得到的辅助索引键值存放于一个缓存中,这时缓存中的数据是根据辅助索引键值排序的。
  2. 将缓存中的键值根据RowID进行排序。
  3. 根据RowID的排序顺序来访问实际的数据文件。

MRR优化的优点

  1. MRR使数据访问变得较为顺序。在查询辅助索引时,首先根据得到的查询结果,按照主键进行排序,并按照主键排序的顺序进行书签查找。
  2. 减少缓冲池中页被替换的次数。
  3. 批量处理对键值的查询操作。

适用场景

适用于range,ref,eq_ref类型的查询。

Multi-Range Read优化

Multi-Range Read优化的目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问。

MRR的工作方式

  1. 将查询得到的辅助索引键值存放于一个缓存中,这时缓存中的数据是根据辅助索引键值排序的。
  2. 将缓存中的键值根据RowID进行排序。
  3. 根据RowID的排序顺序来访问实际的数据文件。

MRR优化的优点

  1. MRR使数据访问变得较为顺序。在查询辅助索引时,首先根据得到的查询结果,按照主键进行排序,并按照主键排序的顺序进行书签查找。
  2. 减少缓冲池中页被替换的次数。
  3. 批量处理对键值的查询操作。

适用场景

适用于range,ref,eq_ref类型的查询。

参数配置

Multi-Range Read优化可以通过参数optimizer_switch中的标记(flag)来控制,当mrr为on时,表示启用Multi-Range Read优化。mrr_cost_based标记表示是否通过costbased的方式来选择是否启用mrr。若将mrr设为on,mrr_cost_based设为off,则总是启用Multi-Range Read优化。

mysql> select @@optimizer_switch;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @@optimizer_switch                                                                                                                                                                                                                                                                                                                                                                                               |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

mysql>set @@optimizer_switch="mrr=no,mrr_cost_based=off";
Query OK, 0 rows affected

参数read_rnd_buffer_size用来控制键值的缓冲区大小,默认是256k;

mysql> SET @@read_rnd_buffer_size=524288;
Query OK, 0 rows affected

mysql> SELECT @@read_rnd_buffer_size;
+------------------------+
| @@read_rnd_buffer_size |
+------------------------+
|                 524288 |
+------------------------+
1 row in set

Index Condition Pushdown(ICP)优化

ICP的工作方式

一般情况下,当进行索引查询时,首先根据索引来查找记录,然后再根据WHERE条件来过滤记录。而在支持Index Condition Pushdown后,MySQL数据库会在取出索引的同时,判断是否可以进行WHERE条件的过滤,也就是将WHERE的部分过滤操作放在了存储引擎层。其实就是使用覆盖索引直接来做WHERE条件的过滤。

ICP优化的优点

因为可以直接使用索引来做WHERE条件的过滤,所以就少了去查询聚集索引的IO。

适用场景

支持range、ref、eq_ref、ref_or_null类型的查询

Index Condition Pushdown优化可以将查询效率在原有MySQL 5.5版本的技术上提高23%。而同时启用Mulit-RangeRead优化后,性能还能有400%的提升!

数据结构可视化

https://www.cs.usfca.edu/~galles/visualization/AlGorithms.html Https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html https://www.cs.usfca.edu/~galles/visualization/BTree.html

您可能感兴趣的文档:

--结束END--

本文标题: MySQL索引原理

本文链接: https://www.lsjlt.com/news/5685.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL索引原理
    定义 索引(Index)是帮助MySQL高效获取数据的数据结构。那么什么数据结构可以用来高效的获取数据呢? 查看索引 mysql> show index from user; +-------+------------+----------...
    99+
    2020-02-14
    MySQL索引原理
  • Mysql索引基本原理
      1.Mysql表空间、段、区、页     在讲索引的概念之前我们先说一下mysql中段区页的概念。     表空间是Mysql数据库存储的最高层,默认情况下InnoDB引擎只有一个表空间,所有的数据都是存放在这个表空间内。  ...
    99+
    2017-03-31
    Mysql索引基本原理
  • MySQL索引原理详解
    目录索引是什么索引数据结构树形索引树的动画为什么不是简单的二叉树?为什么不是红黑树?为什么最终选择B+树 而不是B树水平方向可以存放更多的索引key数据量估算叶子节点包含所有的索引字段叶子节点直接包含双向指针,范围查找效...
    99+
    2022-08-19
    MySQL索引原理 MySQL索引
  • MySQL索引失效原理
    目录1、索引失效原因2、再来看看哪些情况会破坏索引的有序性。 - 对索引字段做函数操作 - 隐式类型转换 - 隐式字符编码转换 3、总结 1、索引失效原因 首先看看哪些情况下,将会导...
    99+
    2022-11-12
  • 如何理解MySQL索引原理
    本篇内容主要讲解“如何理解MySQL索引原理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解MySQL索引原理”吧!案例背景假设面试官问你:在电商平台的订...
    99+
    2022-10-19
  • MySql索引原理与操作
    目录1. 什么是索引2. 索引的实现原理3. 添加索引的条件4. 索引的操作1. 创建索引2. 删除索引3. 查看一个sql语句是否使用了索引进行检索5. 索引的失效6. 索引的类型1. 什么是索引 索引是在数据库表的字...
    99+
    2022-09-16
  • mysql索引的工作原理
    小编给大家分享一下mysql索引的工作原理,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!MySQL中索引的简介在MySQL中,索...
    99+
    2022-10-18
  • 什么是MySQL索引原理
    下面一起来了解下什么是MySQL索引原理,相信大家看完肯定会受益匪浅,文字在精不在多,希望什么是MySQL索引原理这篇短内容是你想要的。 索引原理&本质MySQL官方解释:索引是为MySQ...
    99+
    2022-10-18
  • MySQL索引原理是什么
    这篇文章主要介绍MySQL索引原理是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!摘要: 就一起来聊一聊MySQL索引。 什么是索引? 百度百科是这样描述的: 索引是为来加速对表...
    99+
    2022-10-18
  • 什么是mysql的索引原理
    下面讲讲关于mysql的索引原理,文字的奥妙在于贴近主题相关。所以,闲话就不谈了,我们直接看下文吧,相信看完mysql的索引原理这篇文章你一定会有所受益。      ...
    99+
    2022-10-18
  • MySQL的InnoDB索引原理详解
      摘要:   本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节。   InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档)。本着高效学习的...
    99+
    2022-05-18
    mysql InnoDB
  • MySQL的索引原理是什么
    本篇内容介绍了“MySQL的索引原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、索引的本质索引...
    99+
    2022-10-18
  • MySQL索引的原理是什么
    本篇内容介绍了“MySQL索引的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!索引,可能让好很多...
    99+
    2022-10-18
  • MySQL索引的理解学习,面试不问索引原理就是事务原理
    目录 MySQL执行SQL的整体流程 引言, MySQL索引底层学习原因 磁盘介绍(理解磁盘IO) 索引底层数据结构B+树 B+树(聚集索引) B+树(辅助索引) 思考一下为何使用B+树结构, 不是B树, 不是平衡树二叉树,红黑树? 索引总...
    99+
    2023-09-28
    面试 学习 mysql 索引
  • 怎样理解MySQL索引底层原理
    这篇文章给大家介绍怎样理解MySQL索引底层原理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Mysql 作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤...
    99+
    2022-10-18
  • 深入理解 MySQL 索引底层原理
    目录mysql 索引底层数据结构选型哈希表(Hash)二叉查找树(BST)AVL 树和红黑树B 树5.B+树Innodb 引擎和 Myisam 引擎的实现MyISAM 引擎的底层实现(非聚集索引方式)Innodb 引擎的...
    99+
    2022-12-25
    MySQL 索引底层原理 MySQL索引底层实现原理 MySQL数据库索引底层原理
  • 深入理解 MySQL 索引底层原理
    目录Mysql 索引底层数据结构选型哈希表(Hash)二叉查找树(BST)AVL 树和红黑树B 树5.B+树Innodb 引擎和 Myisam 引擎的实现MyISAM 引擎的底层实现...
    99+
    2022-12-25
    MySQL 索引底层原理 MySQL索引底层实现原理 MySQL数据库索引底层原理
  • 索引原理及B树索引
    索引原理及B树索引 http://hongyitong.github.io/2017/01/05/%E7%B4%A2%E5%BC%95%E5%8E%9F%E7%90%86%E5%8F%8AB%E6%A0%91%E7%B4%A2%E...
    99+
    2020-03-30
    索引原理及B树索引
  • mysql中innodb索引原理是什么
    这篇文章主要介绍了mysql中innodb索引原理是什么,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。聚集索引(clustered index)...
    99+
    2022-10-18
  • Mysql索引的实现原理分析
    本篇文章为大家展示了Mysql索引的实现原理分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。  一:Mysql原理与慢查询  MySQL凭借着出色的性能、低廉的成...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作