查找表与索引 区别联系

总览:

  1. 查找表:
    1. 有序查找表:
      1. 2-way平衡树如avl,rb-tree,aa-tree,splay-tree,sized-balance -tree;
      2. skipList:带索引的有序链表
      3. 多路平衡树:b-tree,b+ tree
      4. BST,但效率不保证
    2. 无序查找表:
      1. hash表,实现如unordered-_map/set/multimap/multiset系列
      2. 当key为整数类型,value为bool类型,hash表的特列版本 或者 也可以看出数组的特殊应用:bitmap 实现如std::bitset
      3. bitmap的拓展:bloomFilter
      4. 数组,list等普通容器都可以作为查找表,但查找效率很低或很难保证
      5. 注意:数组在key为ascii码字符时可以作为完美hash表使用

简单谈谈Mysql索引与redis跳表

 更新时间:2019年04月16日 09:53:26   作者:stoneFang   我要评论
这篇文章主要给大家介绍了Mysql索引与redis跳表的相关资料,文中介绍的非常详细,对大家学习或者使用Mysql和redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

摘要

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

问题

如果对以下问题感到困惑或一知半解,请继续看下去,相信本文一定会对你有帮助

  • mysql 索引如何实现
  • mysql 索引结构B+树与hash有何区别。分别适用于什么场景
  • 数据库的索引还能有其他实现吗
  • redis跳表是如何实现的
  • 跳表和B+树,LSM树有和区别呢

解析

首先为什么要把mysql索引和redis跳表放在一起讨论呢,因为他们解决的都是同一种问题,用于解决数据集合的查找问题,即根据指定的key,快速查到它所在的位置(或者对应的value)

当你站在这个角度去思考问题时,还会不知道B+树索引和hash索引的区别吗

数据集合的查找问题

现在我们将问题领域边界划分清楚了,就是为了解决数据集合的查找问题。这一块需要考虑哪些问题呢

  1. 需要支持哪些查找方式,单key/多key/范围查找,
  2. 插入/删除效率
  3. 查找效率(即时间复杂度)
  4. 存储大小(空间复杂度)

我们看下几种常用的查找结构

hash

hash是key,value形式,通过一个散列函数,能够根据key快速找到value

B+树

B+树是在平衡二叉树基础上演变过来,为什么我们在算法课上没学到B+树和跳表这种结构呢。因为他们都是从工程实践中得到,在理论的基础上进行了妥协。

B+树首先是有序结构,为了不至于树的高度太高,影响查找效率,在叶子节点上存储的不是单个数据,而是一页数据,提高了查找效率,而为了更好的支持范围查询,B+树在叶子节点冗余了非叶子节点数据,为了支持翻页,叶子节点之间通过指针连接。

跳表

跳表是在链表的基础上进行扩展的,为的是实现redis的sorted set数据结构。 level0: 是存储原始数据的,是一个有序链表,每个节点都在链上 level0+: 通过指针串联起节点,是原始数据的一个子集,level等级越高,串联的数据越少,这样可以显著提高查找效率,

总结

数据结构实现原理key查询方式查找效率存储大小插入、删除效率
Hash哈希表支持单key接近O(1)小,除了数据没有额外的存储O(1)
B+树平衡二叉树扩展而来单key,范围,分页O(Log(n)除了数据,还多了左右指针,以及叶子节点指针O(Log(n),需要调整树的结构,算法比较复杂
跳表有序链表扩展而来单key,分页O(Log(n)除了数据,还多了指针,但是每个节点的指针小于<2,所以比B+树占用空间小O(Log(n),只用处理链表,算法比较简单

对LSM结构感兴趣的可以看下cassandra vs mongo (1)存储引擎

cassandra vs mongo (1)存储引擎

概括

存储引擎:

B-Tree

缓存管理

缓存管理的核心在于置换算法,置换算法常见的有FIFO(First In First Out),LRU(Least Recently Used)。关系型数据库在LRU的基础上,进行了改进,主要使用LIRS(Low Inter-reference Recency Set)
将缓存分为两级,第一次采用LRU,最近被使用到的数据会进第一级,如果数据在较短时间内被访问了两次或以上,则成为热点数据,进入第二级。避免了进行全表扫描的时候,可能会将缓存中的大量热点数据替换掉。

LSM

Log-Structured Merge Tree:结构化合并树,核心思想就是不将数据立即从内存中写入到磁盘,而是先保存在内存中,积累了一定量后再刷到磁盘中

LSM VS B-Tree

LSM在B-Tree的基础上为了获取更好的写性能而牺牲了部分的读性能,同时利用其它的实现来弥补读性能,比如boom-filter.

1.写

B树的写入,是首先找到对应的块位置,然后将新数据插入。随着写入越来越多,为了维护B树结构,节点得分裂。这样插入数据的随机写概率就会增大,性能会减弱。

LSM 则是在内存中形成小的排好序的树,然后flush到磁盘的时候不断的做merge.因为写入都是内存写,不写磁盘,所以写会很高效。

2.读

B树从根节点开始二分查询直到叶子节点,每次读取一个节点,如果对应的页面不在内存中,则读取磁盘,缓存数据。

LSM树整个结构不是有序的,所以不知道数据在什么地方,需要从每个小的有序结构中做二分查询,找到了就返回,找不到就继续找下一个有序结构。所以说LSM牺牲了读性能。但是LSM之所以能够作为大规模数据存储系统在于读性能可以通过其他方式来提高,比如读取性能更多的依赖于内存/缓存命中率而不是磁盘读取。

Cassandra

Cassandra是一个写性能优于读性能的NoSql数据库,写性能好一个原因在于选择了LSM存储引擎。

Mongo

MMAPv1

Mongo 3.2以前默认使用MMAPv1存储引擎,是基于B-Tree类型的。

边界(padding)

MMAPv1 存储引擎使用一个叫做”记录分配”的过程来为document存储分配磁盘空间。MongoDB与Cassandra不同的是,需要去更新原有的document。如果原有的document空间不足,则需要将这个document移动到新的位置,更新对应的index。这样就会导致一些不必要的更新,和数据碎片。

为了避免出现上述情况,就有了边界的概念,就是为document预分配空间。但是这样就有可能造成资源的浪费。mongo 按照64M,128M,256M…2G的2的冥次方递增策略预分配,最大2G。在数据量小的情况下问题并不明显,但是当达到2G时,磁盘占用量大的问题就出来了。

同样这一点和关系型数据库也不一样,关系型数据库对于长记录数据会分开存储。


MMAPv1使用collection级别的锁,即一个collecion增,删,改一次只能有一个。在并发操作时,就会造成等待。

WiredTiger

3.2及其以后的默认存储引擎,同样是基于B-Tree的。采用了lock-free,风险指针等并发技术,使得在多核机器上工作的更好。

锁级别为document。并且引入了compression,减少了磁盘占用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

                    <div class="art_xg">
                    <h4>您可能感兴趣的文章:</h4><ul><li><a href="/article/161779.htm" title="新手学习MySQL索引" target="_blank">新手学习MySQL索引</a></li><li><a href="/article/161768.htm" title="由不同的索引更新解决MySQL死锁套路" target="_blank">由不同的索引更新解决MySQL死锁套路</a></li><li><a href="/article/161765.htm" title="通过唯一索引S锁与X锁来了解MySQL死锁套路" target="_blank">通过唯一索引S锁与X锁来了解MySQL死锁套路</a></li><li><a href="/article/161520.htm" title="分享几道关于MySQL索引的重点面试题" target="_blank">分享几道关于MySQL索引的重点面试题</a></li><li><a href="/article/161156.htm" title="Mysql中的索引精讲" target="_blank">Mysql中的索引精讲</a></li><li><a href="/article/159494.htm" title="MySQL学习(七):Innodb存储引擎索引的实现原理详解" target="_blank">MySQL学习(七):Innodb存储引擎索引的实现原理详解</a></li><li><a href="/article/159078.htm" title="使用shell脚本来给mysql加索引的方法" target="_blank">使用shell脚本来给mysql加索引的方法</a></li><li><a href="/article/159017.htm" title="MySQL批量插入和唯一索引问题的解决方法" target="_blank">MySQL批量插入和唯一索引问题的解决方法</a></li><li><a href="/article/163527.htm" title="高效利用mysql索引指南" target="_blank">高效利用mysql索引指南</a></li></ul>
                    </div>
					<p class="tip">如您对本文有所疑义或者对本文内容提供补充建议,请联系小编<a href="http://wpa.qq.com/msgrd?v=3&amp;uin=2998481778&amp;site=jb51net&amp;menu=yes" target="_blank"><img border="0" src="https://pub.idqqimg.com/qconn/wpa/button/button_111.gif" alt="点击这里给我发消息" title="点击这里给我发消息"></a>,本站会保留修改者版权</p><div class="lbd_bot clearfix">
					<div id="_1a3bpa1onh9"><ins style="width:0px;height:0px;margin-top:0px;"></ins><iframe width="820" frameborder="0" height="250" scrolling="no" src="https://pos.baidu.com/s?hei=250&amp;wid=820&amp;di=u4846790&amp;ltu=https%3A%2F%2Fwww.jb51.net%2Farticle%2F159790.htm&amp;psi=9a40c3d284ff633e7fd897078a35aa5f&amp;dai=1&amp;dtm=HTML_POST&amp;cfv=0&amp;cmi=33&amp;exps=111000,110011&amp;cdo=-1&amp;tlm=1583993157&amp;ti=%E7%AE%80%E5%8D%95%E8%B0%88%E8%B0%88Mysql%E7%B4%A2%E5%BC%95%E4%B8%8Eredis%E8%B7%B3%E8%A1%A8_Mysql_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&amp;pss=1440x7957&amp;ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DRa93joM0haE1bYJ5Qk5ezT8n15W1FH5Hs5_ne3rVbXMjY0U8eSH4HK6ikPw7AHZnxORkRrkt2zxWYnBIwPMj-K%26wd%3D%26eqid%3Dd8804a6e0008694c000000045e69d061&amp;pis=-1x-1&amp;drs=1&amp;pcs=1440x789&amp;psr=1440x900&amp;dri=0&amp;tcn=1583993157&amp;cja=false&amp;dis=0&amp;ps=6158x135&amp;cpl=4&amp;prot=2&amp;chi=1&amp;tpr=1583993157298&amp;ccd=24&amp;ari=2&amp;dc=3&amp;par=1440x900&amp;cce=true&amp;ant=0&amp;col=en-US&amp;cec=GBK"></iframe></div><script type="text/javascript" src="//jscode.jbzj.com/production/ql/common/h/source/n/h/production/kmtr.js"></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值