当前位置: 首页 > news >正文

数据结构与算法之美学习笔记:50 | 索引:如何在海量数据中快速查找某个数据?

目录

  • 前言
  • 为什么需要索引?
  • 索引的需求定义
  • 构建索引常用的数据结构有哪些?
  • 总结引申

前言

在这里插入图片描述
本节课程思维导图:
在这里插入图片描述
在第 48 节中,我们讲了 MySQL 数据库索引的实现原理。MySQL 底层依赖的是 B+ 树这种数据结构。留言里有同学问我,那类似 Redis 这样的 Key-Value 数据库中的索引,又是怎么实现的呢?底层依赖的又是什么数据结构呢?

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

为什么需要索引?

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

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

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

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

索引的需求定义

索引的概念不难理解,我想你应该已经搞明白。接下来,我们就分析一下,在设计索引的过程中,需要考虑到的一些因素,换句话说就是,我们该如何定义清楚需求呢?

对于系统设计需求,我们一般可以从功能性需求和非功能性需求两方面来分析,这个我们之前也说过。因此,这个问题也不例外。

  1. 功能性需求对于功能性需求需要考虑的点,我把它们大致概括成下面这几点。
    数据是格式化数据还是非格式化数据?要构建索引的原始数据,类型有很多。我把它分为两类,一类是结构化数据,比如,MySQL 中的数据;另一类是非结构化数据,比如搜索引擎中网页。对于非结构化数据,我们一般需要做预处理,提取出查询关键词,对关键词构建索引。

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

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

单值查找还是区间查找?所谓单值查找,也就是根据查询关键词等于某个值的数据。这种查询需求最常见。所谓区间查找,就是查找关键词处于某个区间值的所有数据。你可以类比 MySQL 数据库的查询需求,自己想象一下。实际上,不同的应用场景,查询的需求会多种多样。

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

实际上,不同的场景,不同的原始数据,对于索引的需求也会千差万别。我这里只列举了一些比较有共性的需求。

  1. 非功能性需求讲完了功能性需求,我们再来看,索引设计的非功能性需求。

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

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

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

我刚刚从很宏观的角度,总结了在索引设计的过程中,需要考虑的一些共性因素。现在,我们就来看,对于不同需求的索引结构,底层一般使用哪种数据结构。

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

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

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

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

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

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

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

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

总结引申

今天这节算是一节总结课。我从索引这个非常常用的技术方案,给你展示了散列表、红黑树、跳表、位图、布隆过滤器、有序数组这些数据结构的应用场景。学习完这节课之后,不知道你对这些数据结构以及索引,有没有更加清晰的认识呢?

从这一节内容中,你应该可以看出,架构设计离不开数据结构和算法。要想成长为一个优秀的业务架构师、基础架构师,数据结构和算法的根基一定要打稳。因为,那些看似很惊艳的架构设计思路,实际上,都是来自最常用的数据结构和算法。

相关文章:

数据结构与算法之美学习笔记:50 | 索引:如何在海量数据中快速查找某个数据?

目录 前言为什么需要索引?索引的需求定义构建索引常用的数据结构有哪些?总结引申 前言 本节课程思维导图: 在第 48 节中,我们讲了 MySQL 数据库索引的实现原理。MySQL 底层依赖的是 B 树这种数据结构。留言里有同学问我&#xff…...

Python(SQLite)executescript用法

SQLite 数据库模块的游标对象还包含了一个 executescript() 方法,这不是一个标准的 API 方法,这意味着在其他数据库 API 模块中可能没有这个方法。但是这个方法却很实用,它可以执行一段 SQL 脚本。 例如,如下程序使用 executescr…...

BUUCTF-Real-[ThinkPHP]IN SQL INJECTION

目录 漏洞描述 漏洞分析 漏洞复现 漏洞描述 漏洞发现时间&#xff1a; 2018-09-04 CVE 参考&#xff1a;CVE-2018-16385 最高严重级别&#xff1a;低风险 受影响的系统&#xff1a;ThinkPHP < 5.1.23 漏洞描述&#xff1a; ThinkPHP是一款快速、兼容、简单的轻量级国产P…...

python安装步骤

安装 Python 的步骤如下&#xff1a; 在 Python 官方网站&#xff08;https://www.python.org&#xff09;上下载 Python 安装程序。运行下载的安装程序。在安装程序中选择要安装的 Python 版本&#xff08;通常选择最新版本&#xff09;&#xff0c;并选择安装目录。确保勾选…...

BlueLotus 下载安装使用

说明 蓝莲花平台BlueLotus&#xff0c;是清华大学曾经的蓝莲花战队搭建的平台&#xff0c;该平台用于接收xss返回数据。 正常执行反射型xss和存储型xss&#xff1a; 反射型在执行poc时&#xff0c;会直接在页面弹出执行注入的poc代码&#xff1b;存储型则是在将poc代码注入用…...

.[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复

导言&#xff1a; 在当今数字化时代&#xff0c;勒索病毒已成为网络安全领域的一大威胁。其中一种新近出现的勒索病毒是由[hudsonLcock.li].mkp[hendersoncock.li].mkp[myersairmail.cc].mkp制作的&#xff0c;它以其高效的加密算法和勒索方式而备受关注。本文91数据恢复将介绍…...

基于SpringBoot和PostGIS的震中影响范围可视化实践

目录 前言 一、基础数据 1、地震基础信息 2、全国行政村 二、Java后台服务设计 1、实体类设计 2、Mapper类设计 3、控制器设计 三、前端展示 1、初始化图例 2、震中位置及影响范围标记 3、行政村点查询及标记 总结 前言 地震等自然灾害目前还是依然不能进行准确的预…...

JUnit实践教程——Java的单元测试框架

前言 大家好&#xff0c;我是chowley&#xff0c;最近在学单元测试框架——JUnit&#xff0c;写个博客记录一下&#xff01; 在软件开发中&#xff0c;单元测试是确保代码质量和稳定性的重要手段之一。JUnit作为Java领域最流行的单元测试框架&#xff0c;为开发人员提供了简单…...

选择大语言模型:2024 年开源 LLM 入门指南

作者&#xff1a;来自 Elastic Aditya Tripathi 如果说人工智能在 2023 年起飞&#xff0c;这绝对是轻描淡写的说法。数千种新的人工智能工具被推出&#xff0c;人工智能功能被添加到现有的应用程序中&#xff0c;好莱坞因对这项技术的担忧而戛然而止。 甚至还有一个人工智能工…...

ElastAlert 错误日志告警

文章目录 前言一、ElastAlert 概览1.1 简介1.2 ElastAlert 特性 二、ElastAlert 下载部署2.1 安装 Python3 环境2.2 下载 ElastAlert2.3 部署 ElastAlert 三、接入平台3.1 对外接口层3.2 服务层 前言 ElastAlert 是 Yelp 公司基于 python 开发的 ELK 日志告警插件&#xff0c;…...

假设检验的过程

假设检验的核心思想是小概率事件在一次实验中不可能发生&#xff0c;假设检验就是利用小概率事件的发生进行反正。学习假设检验&#xff0c;有几个概念不能跳过&#xff0c;原假设、p值 1.原假设 假设检验的基本过程如下&#xff1a; 1&#xff09;做出一个假设H0&#xff0c…...

vue项目打包部署到flask等后端服务里面,实现前后端不分离部署,解决空白页面和刷新页面not fount问题

1. 编译模式一定要设置为esnext&#xff0c;否则会报错&#xff1a; Strict MIME type checking is enforced for module scripts per HTML spec.Expected a JavaScript module script but the server responded with a MIME type of "text/plain". 具体解释可以看vi…...

labelimg 在pycharm下载使用

labelimg 使用数据标注工具 labelimg 制作数据集 在pycharm中搜索labelimg 选择版本安装 labelimg install 使用数据标注工具制作数据集 启动 带参数启动 1、cmd cd到指定目录 2、带参数启动标注工具 左侧可以选择切换为需要的数据格式 一些快捷键 和自动保存&#xff0c…...

STM32/C51开发环境搭建(KeilV5安装)

Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统&#xff0c;与汇编相比&#xff0c;C语言在功能上、结构性、可读性、可维护性上有明显的优势&#xff0c;因而易学易用。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等…...

前端开发 :(二)HTML基础

1. 介绍HTML 1.1 HTML的定义和作用 HTML&#xff08;HyperText Markup Language&#xff09;是一种标记语言&#xff0c;用于创建和设计网页的结构和内容。它通过使用标签来描述文档的结构&#xff0c;使得浏览器能够正确地解释和显示页面。 1.2 HTML的发展历史 HTML的发展…...

小米平板6获取root权限教程

1. 绑定账号 1> 打开"设置-我的设备-全部参数-连续点击MIUI版本按钮"&#xff0c;直到提示已打开开发者模式( p s : 这里需要重点关注红框平板型号和 M I U I 版本&#xff0c;例如我这里平板型号是 X i a o m i P a d 6 &#xff0c; M I U I 版本是 14.0.10 &am…...

01. k210-命令行环境搭建(ubuntu环境)

本文主要讲解k210在ubuntu23.04操作系统中的环境搭建 1.获取工具链 github下载工具链 截止到目前最新版本是:Kendryte GNU Toolchain v8.2.0-20190409[Pre-release]。 编译好的镜像有ubuntu版本和windows版本&#xff0c;本章我们主要讲解的是ubuntu系统的开发环境。 Versio…...

Spring Boot3整合Redis

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 1.导依赖 2.配置连接信息以及连接池参数 3.配置序列化方式 4.编写测试 前置条件 已经初始化好一个spr…...

算法之美_2024

算法与数据结构进阶 – liuyubobo 学习链接 &#xff1a; 算法与数据结构 玩转算法面试 – Leetcode真题分门别类讲解 学习链接&#xff1a;玩转算法面试 LLM行业领军大佬 带你转型大语言模型 学习链接&#xff1a;LLM 区块链 学习链接&#xff1a;区块链 运维测试 学…...

Leetcode刷题笔记题解(C++):590. N 叉树的后序遍历

思路&#xff1a;类似于二叉树的排序&#xff0c;这里需要将子树进行依次递归遍历&#xff0c;前序遍历也与之类似 /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node() {}Node(int _val) {val _val;}Node(int _val, vector<N…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...