------ 本文是学习算法的笔记,《数据结构与算法之美》,极客时间的课程 ------

前面讲过MySQL数据库索引实现原理,底层是依赖B+树这种数据结构来实现的。那类似Redisp 这要的Key-Value数据库中的索引,又是怎么实现的呢?底层依赖的又是什么数据结构呢?

为什么需要索引?

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

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

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

索引这个概念,非常好理解。你可以类比书籍的目录来理解。如果没有目录,我们想要查找某个知识点的时候,就要一页一页的翻。通过目录,我们就可以快速定位相关的知识点的页数,查找的速度也会有质的提高。

索引的需求定义

索引的概念不难理解,在设计索引的过程中,需要考虑一些因素,换名话说,我们该如何定义清楚需求呢?

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

1. 功能性需求

对于功能性需求大致要考虑以下几点。

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

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

索引是存储在内存还是硬盘?如果索引存储在内存中,那技术要求的速度肯定要比存储的磁盘中的高。但是,如果原始数据量很大的情况下,对应的索引可能也会很大。这个时候,因为内存有限,我们可能就不得不将索引存储在硬盘中了。实际上,还有第三种情况,那就是一部分存储在内存,一部分存储在磁盘,这样就可以兼顾内存消耗和查询效率。

单值查找还是区间查找?所谓单值查找,也就是根据查询关键词等于某个值的数据。这种查询需求最常见。所谓区间查找,就是查找关键词处于某个区间值的所有数据。实际上,不同的应用场景,查询的需求会多种多样。

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

实际上,不同的场景,不同的原始数据,对于索引的需求也会千差万别。

2.非功能性需求

不管是存储在内存中还是磁盘中,索引对存储空间的消耗不能过大。如果存储在内存中,索引对占用存储空间的限制就会非常苛刻。毕竟内存空间非常有限,一个中间件启动后就占用几个GB的内存,开发者显然是无法接受的。如果存储在硬盘中,那索引对占用存储空间的限制,稍微会放宽一些。但是,我们也不能掉以轻心。因为,有时候,索引对存储空间消耗会超过数据。

在考虑索引查询效率的同时,我们还是考虑索引的维护成本。索引的目的是提高查询效率,但是,基于动态数据集合构建的索引,我们还要考虑到索引的维护成本。因为在原始数据动态增删改的同时,我们也需要动态的更新索引。而索引的更新势必会影响到增删改的操作性能。

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

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

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

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

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

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

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

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

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

索引:如何在海量数据中快速查找某个数据?相关推荐

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

    亲测可用,若有疑问请私信 在[B+树]:MySQL数据库索引是如何实现的?中,我们讲了MySQL数据库索引的实现原理.MySQL底层依赖的是B+树这种数据结构.那类似Redis这样的Key-Value ...

  2. php对pdf关键字定位,如何在PDF文件中快速查找关键字

    有时候我们在阅读和编辑PDF文章时需要对PDF文件里的重要关键词进行查找,但如果PDF文章内容过长,怎么才能快速查找出想要查找的关键字? 想要在PDF文件中快速查找出关键字,那么利用迅捷PDF编辑器进 ...

  3. Cadence OrCAD原理图中快速查找元件的方法

    Cadence OrCAD原理图中快速查找元件和网络方法 本章节将教大家如何在OrCAD原理图中根据元件位号快速查找元件的两个方法. 方法一:在.obj页面的"File"标签下查找 ...

  4. matlab换挡程序,一种基于MATLAB换挡过程中快速锁定分析数据的方法与流程

    本发明涉及汽车变速器数据分析,特别的,涉及一种基于matlab换挡过程中快速锁定分析数据的方法. 背景技术: 自动变速器的核心功能是能根据驾驶员意图进行自动换挡,解放驾驶员的左脚:在自动变速器的使用过 ...

  5. 如何在 Windows 中快速查找文档

    近几年,随着硬盘介质价格的大幅度下降,各位电脑迷们的个人硬盘容量越来越大,动辄五六十G,甚至上百G都不足为奇,这在前几年是无法想象的.但是硬盘大了,存放的文档多了,查找速度慢的烦恼也随之来了.其实在W ...

  6. centos7 vim查找_如何在 Vim/Vi 中快速查找和替换文本内容

    Vim 是 Vi 多模式命令行编辑器的加强版,通常默认的Unix或Linux系统中都默认自带Vi命令编辑器.当然,为了更好的体验,如果系统默认没有安装Vim,建议安装Vim. 通过本文的讲解,你将学会 ...

  7. 在字符串中 快速查找

    最近更新:28th 十二月, 2016 很多时候,我们需要在字符串中执行查找,以判断过滤指定的内容出来.比如过在落格输入法当中,就需要用辅码过滤出需要的候选词. 一般来说,查找和对比肯定是数字来的最快 ...

  8. 海量数据:快速查找一个数字是否出现在40亿个数字中

    腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 看到问题的想法是采用bitmap:1个字节可以表示8个整数是否出现 ...

  9. python寻峰算法_在python中快速查找峰和质心

    我正在尝试在python中开发一种快速算法,以查找图像中的峰值,然后找到这些峰值的质心.我使用scipy.ndimage.label和ndimage.find_objects编写了以下代码来查找对象. ...

最新文章

  1. py2与py3的区别
  2. 第100天:CSS3中animation动画详解
  3. 启动 Tensorboard
  4. 开学综合症有救了!17篇最新AI论文不容错过
  5. neutron plugin 与 extension 编写流程
  6. java socket 二次发送_发过2次帖子,都没有了,再发。JAVA中SOCKET通信中的数据压缩问题...
  7. 调用模块,加入系统路径
  8. c#操作excel后关闭excel.exe的方法
  9. for相关 java_Java学习之for循环相关知识梳理
  10. sass 安装和使用
  11. 路由器网络性能测试软件,路由器性能测试
  12. URL传递中文、Ajax传递中文,Java如何编码如何解决乱码
  13. ssis 循环导入数据_使用集成服务(SSIS)包从Amazon S3 SSIS存储桶导入数据
  14. 搜狗词库合集分享_Rime小狼毫
  15. 无线桥接:没有网口解决nas有线组网问题
  16. 在Virtualbox虚拟机中安装MSDOS(简易教程)
  17. 文曲星猜数字游戏java代码_文曲星猜数字游戏6步算法(含代码)
  18. MySQL事务中幻读实践
  19. zanti html恶搞,Html.AntiForgeryToken 突然报这个错误 太奇怪了
  20. 计算机表格增加,电脑中给Excel表格添加水印效果的方法

热门文章

  1. ./configure 的配置和用法
  2. configure 配置选项
  3. 新一代分布式实时流处理引擎Flink入门实战之先导理论篇-上
  4. 数据以Excel导出
  5. linux脚本的数据输出到excel,将CSV数据输出到EXCEL
  6. 膜拜一下wjmzbmr500+的代码
  7. 工作就是我们人生中一个巨大的悖论
  8. 画论43 王世贞《艺苑巵言·论画》
  9. 绘制曲线图origin画图
  10. 差速机器人的纯轨迹跟踪仿真(Matlab)