【索引】:如何在海量数据中快速查找某个数据?

亲测可用,若有疑问请私信

【B+树】:MySQL数据库索引是如何实现的?中,我们讲了MySQL数据库索引的实现原理。MySQL底层依赖的是B+树这种数据结构。那类似Redis这样的Key-Value数据库中的索引,又是怎么实现的呢?底层依赖的有是什么数据结构呢

 

今天,我们来讲一下索引这种常用的技术解决思路,底层往往会依赖哪些数据结构。同时,通过索引这个应用场景,我也带你回顾一下,之前我们学过的几种支持动态集合的数据结构。


为什么需要索引?

在实际的软件开发中,业务纷繁复杂。但是万变不离其宗,如果抛开这些业务和功能的外壳,它们的本质都可以抽象为“对数据的存储和计算”。对应到数据结构和算法中,那“存储”需要的就是数据结构,“计算”需要的就是算法。

对于存储的需求,功能上不外乎增删查改。这其实并不复杂,但是一旦存储的数据很多,那性能就成了这些系统要关注的重点,特别是在一些跟存储相关的基础系统(比如MySQL数据库、分布式文件系统等)、中间件(比如消息中间件RocketMQ等)中。

“如何节省存储空间,如何提高数据增删改查的执行效率”,这样的问题就成了设计的重点。而这些系统的实现,都离不开一个东西,那就是索引。索引设计的好坏,直接决定了这些系统是否优秀。

索引这个概念,非常好理解。可以类比书籍的目录来理解。通过目录我们可以快速定位相关知识点的页数,查找的速度也会有质的提高。


索引的需求定义

对于系统设计需求,我们一般可以从功能性需求非功能性需求两方面来分析。

1.功能性需求

数据是格式化数据还是非格式化数据?要构建索引的原始数据,类型有很多。我把它分为两类,一类是结构化数据,比如MySQL中的数据;另一类是非结构化数据,比如搜索引擎中的网页。对于非结构化数据,我们一般需要做预处理,提取出查询关键词,对关键词构建索引。

数据是静态数据还是动态数据?如果原始数据是一组静态数据,也就是说,不会有数据的增加、删除、更新操作,那么我们在构建索引的时候只需要考虑查询效率就可以了。这样索引的构建就相对简单些。不过大部分情况下我们都是对动态数据构建索引,也就是说,我们不仅要考虑到索引的查询效率,在原始数据更新的同时,我们还需要动态的更新索引。支持动态数据集合的索引,设计起来相对也要更加复杂些。

索引存储在内存还是硬盘?还有种情况是一部分存储在内存,一部分存储在硬盘,这样可以兼顾内存消耗和查询效率。

单值查找还是区间查找

单关键词查找还是多关键词组合查找?对于单关键词的查找,索引构建起来相对简单些。对于多关键词查询来说,要分多种情况。像MySQL这种结构化数据的查询需求,我们可以实现针对多个关键词的组合,建立索引;对于像搜索引擎这样的非结构数据的查询需求,我们可以针对单个关键词构建索引,然后通过集合操作,比如求并集、求交集等,计算出多个关键词组合的查询结果。

2. 非功能性需求

不管是存储在内存还是磁盘中,索引对存储空间的消耗不能过大

在考虑索引查询效率的同时,我们还要考虑索引的维护成本。即动态的更新索引的成本。


构建索引的常用数据结构有哪些?

实际上,常用来构建索引的数据结构,就是我们之前讲过的几种支持动态数据集合的数据结构。比如,散列表、红黑树、跳表、B+树。除此之位,位图、布隆过滤器可以作为辅助索引,有序数组可以用来对静态数据构建索引。

散列表增删改查操作的性能非常好,时间复杂度是O(1)。一些键值数据库,比如Redis、Memcache,就是使用散列表来构建索引的。这类索引,一般都构建在内存中

红黑树作为一种常用的平衡二叉查找树,数据插入、删除、查找的时间复杂度是O(logn),也非常适合用来构建内存索引。Ext文件系统中,对磁盘块的索引,用的就是红黑树

B+树比起红黑树来说,更加适合构建存储在磁盘中的索引。B+树是一个多叉树,所以对相同个数的数据构建索引,B+树的高度要低于红黑树。当借助索引查询数据的时候,读取B+树索引,需要的磁盘IO次数更少。所以大部分关系型数据库的索引,比如MySQL、Oracle,都是用B+树来实现的

跳表也支持快速添加、删除、查找数据。而且,我们通过灵活调整索引节点个数和数据个数之间的比例,可以很好的平衡索引对内存的消耗及其查询效率。Redis中的有序集合,就是用跳表来实现的

除了散列表、红黑树、B+树、跳表之外,位图和布隆过滤器这两个数据结构,也可以用于索引中,辅助存储在磁盘中的索引,加速数据查找的效率。我们看下具体怎么做的:

我们知道,布隆过滤器有一定的判错率。但我们可以规避它的短处,发挥它的长处。尽管对于判定存在的数据,有可能不存在。但对于判定不存在的数据,那肯定就不存在。而且布隆过滤器还有一个更大的特点,就是占用的内存非常少。我们可以针对数据构建一个布隆过滤器,并且存储在内存中。当要查询数据的时候,我们可以先通过布隆过滤器,判定是否存在。如果布隆过滤器判定数据不存在,就没必要读取磁盘中的索引了。对于数据不存在的情况,数据查询更加快速了

实际上,有序数组也可以被作为索引。如果数据是静态的,也就是不会有插入、删除、更新操作,那我们可以把数据的关键词(查询用的)抽取出来,组织成有序数组,然后利用二分查找算法来快速查找数据


课后思考

你知道基础系统、中间件、开源软件等系统中,有哪些用到了索引吗?这些系统的索引是如何实现的?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值