青年IT男

个人从事金融行业,就职过易极付、思建科技等重庆一流技术团队,目前就职于某网约车平台负责整个支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。

Mysql索引那些事儿?

Mysql索引那些事儿?

什么是索引?

  • 索引在搜索引擎优化简单解释

  指已经被收录且参与关键词排名的页面。

  • 索引的通俗解释

  索引就像是图书的目录,根据目录中的页码快速找到所需内容。

  • 索引在百度百科中的解释

  在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。

MySQL官方对索引的定义为:

索引(Index)是帮助MySQL高效获取数据的数据结构。我们可以简单理解为:快速查找排好序的一种数据结构。Mysql索引主要有两种结构:B+Tree索引和Hash索引。我们平常所说的索引,如果没有特别指明,一般都是指B树结构组织的索引(B+Tree索引)

有哪些索引算法

hash算法
  • 什么是hash

    如果有编程经验的小伙伴都知道不管是哪种语言都是有hash实现,简单来说就是一个key通过一个hash(key)算法后得到一个固定长度值,可以通过这个计算后的值与存放数据容器长度取模后的值做索引,快速定位元素(可以看作类似数组索引),查询时间复杂度为O(1),在java里面一个对象可以重写hashCode()方法。

  • hash数据结构

    hash

  • 存在问题

    • 只支持等值索引定位

    hash算法虽然能快速定位元素位置,时间复杂度O(1)查询速度是相当可观的,but这个作为mysql数据库索引算法有个致命问题就是不能实现条件范围查询

    比如:

    select * from jion_left where id<10
    

    因为hash只能做到值定位,不能做到范围查询

    select * from jion_left where id=10
    
    • 不支持排序

    在日常工作中经常会用到查询结果排序,因为hash并不支持范围查询只支持等值查询,所以这里的排序是不支持的,因为排序需要有集合数据才能作排序,只有一个数据还撒顺序呢

    比如:

    select * from jion_left  order by id
    
二叉树
  • 二叉排序树是一个空树,或者是具有如下性质的二叉树:(左中右,小中大)
    • 若它的左子树不为空,则左子树上的所有节点的值均小于它的根节点的值;
    • 若它的右子树不为空,则右子树上的所有节点的值均大于它的根节点的值;
    • 左右子树都是二叉排序树。
  • 二叉排序树的数据操作效率:
    1.查找效率最好为O(log n)、最坏为O(n);
    2.插入效率和查找效率相同(先查找插入的位置,且只插入到叶子节点);
    3.删除效率最好为O(log n) + O(1)(只有左或者右子树),最坏为O(log n) + O(log n)(只有左右子树同时存在)。

    tree2

倾斜二叉树

那么什么是倾斜二叉树呢?大家可以在这个网站模拟插入连续的增长数据,https://www.cs.usfca.edu/~galles/visualization/BST.html可以看到数据是倾斜一方,这样就形成了一个全链表数据,数据查询时间复杂度为O(n),类似全表扫描。

如图所示

tree-model1

平衡二叉树

tree-model1

  • 什么是平衡二叉树

    平衡二叉树是空树或者左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是平衡二叉树。
    平衡二叉树牺牲了插入和删除数据的代价,但是提高了查询效率(稳定查询效率为O(log n))。

  • 存在问题

    索引是存在于索引文件中,是存在于磁盘中的。因为索引通常是很大的,因此无法一次将全部索引加载到内存当中,因此每次只能从磁盘中读取一个磁盘页的数据到内存中(Mysql数据页大小为4K)。而这个磁盘的读取的速度较内存中的读取速度而言是差了好几个级别。

    注意,我们说的平衡二叉树结构,指的是逻辑结构上的平衡二叉树,其物理实现是数组。然后由于在逻辑结构上相近的节点在物理结构上可能会差很远。因此,每次读取的磁盘页的数据中有许多是用不上的。因此,查找过程中要进行许多次的磁盘读取操作。

    而适合作为索引的结构应该是尽可能少的执行磁盘IO操作,因为执行磁盘IO操作非常的耗时。因此,平衡二叉树并不适合作为索引结构。

红黑树

tree-model3

  • 什么是红黑树

    红黑树是一种自平衡二叉排序树,特征如下:

    • 节点是红色或者是黑色;
    • 根节点是黑色;
    • 所有叶子节点都是黑色(叶子节点的值都是NULL);
    • 每个红色节点的两个子节点都是黑色(即从根到叶子遍历不能出现两个连续的红节点);
    • 从任意一个节点到每个叶子节点的所有简单路径都包含相同数据的黑色节点。
      红黑树解决的问题,它可以在O(log n)时间复杂度内实现查找,插入和删除,任何不平衡都会在三次旋转内解决。
  • 存在问题

    红黑树这种结构,明显要深的多(树高度越高IO次数越多)。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。

    也就是说,使用红黑树(平衡二叉树)结构的话,每次磁盘预读中的很多数据是用不上的数据。因此,它没能利用好磁盘预读的提供的数据。然后又由于深度大(较B树而言),所以进行的磁盘IO操作更多。

B树

tree-model4

  • 什么是B树(多路查找树)

    B树就像一棵“m叉搜索树”(m是子树的最大个数),时间复杂度为O(logm(n))。然而,B树设计了一种高效简单的维护操作,使B树的深度维持在约log(ceil(m/2))(n)~logm(n)之间,大大降低树高

  • 特征

    • 根节点至少有两个子女节点;
    • 每个非根节点包含的关键字个数i满足:n/2 – 1 < i < n -1;
    • 除根节点以外的所有节点(不包括叶子节点)的度数正好是关键字的总数+1,故内部子树个数k满足:n/2 < k < n -1;
    • 所有的叶子节点都位于同一层。
  • B树优点

    B树的每个节点可以存储多个关键字,它将节点大小设置为磁盘页的大小,充分利用了磁盘预读的功能。每次读取磁盘页时就会读取一整个节点。也正因每个节点存储着非常多个关键字,树的深度就会非常的小。进而要执行的磁盘读取操作次数就会非常少,更多的是在内存中对读取进来的数据进行查找。

    B树的查询,主要发生在内存中,而平衡二叉树的查询,则是发生在磁盘读取中。因此,虽然B树查询的次数不比平衡二叉树的次数少,但是相比起磁盘IO速度,内存中比较的耗时就可以忽略不计了。因此,B树更适合作为索引。

  • 为什么适合作索引

    平衡二叉树不适合作为索引。那么什么才适合作为索引——B树。

    平衡二叉树没能充分利用磁盘预读功能,而B树是为了充分利用磁盘预读功能来而创建的一种数据结构,也就是说B树就是为了作为索引才被发明出来的的。

  • 存在问题

    B树在提高IO性能的同时,并没与解决元素遍历时效率低下的问题,无论是B树还是B+树由于前边几层反复query,因此早已被加载入内存,不会出现读磁盘IO。一般启动的时候,就会主动换入内存。在内存中B+树并没有优势,只有在磁盘中B+树的威力才能显现。

Mysql数据库引擎
MyISAM
  • 什么是MyiSAM?

    MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针,MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。主键索引和辅助索引是独立的。

    • 数据存储结构

    b+tree

InnoDB
  • 什么是InnoDB

    InnoDB是聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是在一个文件,主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值。(非主键索引叶子节点保存的是数据主键,根据主键到主键索引查找叶子结点数据,减少数据冗余)

  • 数据存储结构

    b+tree2

Mysql索引算法B+Tree

tree-model5

  • 什么是B+Tree
    • MySQL中也是使用B+树作为索引。它是B树的变种,因此是基于B树来改进的。

    • B+树:有序数组链表+平衡多叉树;

    • B+树的关键字全部存放在叶子节点中,非叶子节点用来做索引,而叶子节点中有一个指针指向一下个叶子节点。做这个优化的目的是为了提高区间访问的性能。而正是这个特性决定了B+树更适合用来存储外部数据。
  • 特征

    • 有n个子树的节点含有n个关键字;
    • 所有叶子节点包含了全部关键字的信息,以及指向这些关键字记录的指针,且叶子节点本身依赖关键字的大小,即自小而大顺序连接;
    • 所有的非终端节点可以看成索引的一部分,节点中包含了其他子树的最大或最小关键字。

局部性原理与磁盘预读

由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:
当一个数据被用到时,其附近的数据也通常会马上被使用。
程序运行期间所需要的数据通常比较集中。
由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

关注我

在这里插入图片描述

0
青年IT男

个人从事金融行业,就职过易极付、思建科技等重庆一流技术团队,目前就职于某网约车平台负责整个支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。

评论已关闭。

This site is protected by wp-copyrightpro.com