高效查询:位图、B+树
1. 位图(BitMap)与布隆过滤器(Bloom Filter)
1.1. 问题背景与解决方案
问题背景
场景:网页爬虫判重
- 搜索引擎的爬虫会不断地解析网页中的链接并继续爬取。
- 一个网页可能在多个页面中出现,容易重复爬取。
- 需要一种高效机制实现 URL 去重。
基本思路
判重基本逻辑
- 判断某个 URL 是否已爬取(存在);
- 如果未爬取,则继续爬取并加入“已爬取集合”。
所需操作
- 插入 URL
- 查询 URL
- 操作高效(时间复杂度低)
- 内存消耗尽可能低(处理上亿数据)
数据结构比较
数据结构 | 查询效率 | 插入效率 | 空间消耗 | 是否准确 |
散列表(哈希表) | 高(O(1)) | 高(O(1)) | 高(>100GB) | 准确 |
位图(BitMap) | 高(O(1)) | 高(O(1)) | 较低(位级别) | 准确(范围限制) |
布隆过滤器 | 高(O(K)) | 高(O(K)) | 低(约1.2GB) | 有误判(可接受) |
1.2. 位图(BitMap)
位图定义:
- 使用 位(bit)数组表示某个值是否存在。
特点:
- 高效、节省内存(如 1 亿范围只需约 12MB 内存)。
- 适用于整数范围 不太大的场景。
class BitMap:def __init__(self, nbits):"""初始化位图数组。nbits: 需要支持的最大位数。"""self.nbits = nbits# 每个元素为16位,相当于Java中的char,这里使用整数模拟self.bytes = [0] * ((nbits // 16) + 1)def set(self, k):"""将第 k 位设置为 1,表示该数字已出现。"""if k >= self.nbits or k < 0:raise ValueError("Index out of range")byte_index = k // 16bit_index = k % 16self.bytes[byte_index] |= (1 << bit_index)def get(self, k):"""获取第 k 位的状态,判断该数字是否出现。返回 True 表示已出现。"""if k >= self.nbits or k < 0:raise ValueError("Index out of range")byte_index = k // 16bit_index = k % 16return (self.bytes[byte_index] & (1 << bit_index)) != 0
1.3. 布隆过滤器(Bloom Filter)
背景
- 位图不能应对太大范围(如 1~10亿),需进一步优化。
- 布隆过滤器 = 多个哈希函数 + 位图
工作机制
- 使用
K
个哈希函数对元素x
进行哈希,得到下标X1 ~ XK
; - 把位图的
X1 ~ XK
位置置为1
; - 查询时也用
K
个哈希函数,判断对应位是否都为1
;
-
- 是:可能存在(有误判);
- 否:一定不存在。
误判特性
- 误判只会出现在判断“存在”时;
- 可通过合理选择:
-
- 哈希函数个数
K
- 位图大小
m
- 数据规模
n
- 哈希函数个数
- 控制误判率达到可接受范围。
1.4. 应用实例
爬虫URL去重实战应用
使用布隆过滤器优化爬虫判重
- 假设需去重的 URL 数量为 10 亿
- 采用布隆过滤器(位图大小 100 亿位 ≈ 1.2GB)
- 多个哈希函数进行哈希定位
- 内存节省显著(相比于 100GB 级的哈希表)
效率分析
- 散列表:内存密集,频繁字符串比对、指针访问(慢);
- 布隆过滤器:CPU密集,批量哈希计算(快);
-
- 减少缓存miss;
- 减少长字符串比较。
应用拓展场景
- 搜索引擎网页爬虫判重
- 大规模用户访问去重(如每日UV)
- 黑名单检测、垃圾邮件过滤
- CDN 去重缓存
- 数据库缓存穿透保护等
数据结构应用对比:
对比维度 | 散列表 | 位图 | 布隆过滤器 |
精度 | 准确 | 准确(范围小) | 有小概率误判 |
内存占用 | 高 | 中 | 低 |
插入查询 | O(1) | O(1) | O(K)(哈希函数个数) |
应用 | 通用 | 范围小 | 大规模、可容忍误判场景 |
2. B+树:MySQL数据库索引
索引要解决什么问题?
功能性需求:
- 快速根据某个值查询:
SELECT * FROM user WHERE id = 1234
- 快速进行区间查找:
SELECT * FROM user WHERE id > 1234 AND id < 2345
性能需求:
- 查找效率要高(时间)
- 占用内存尽量少(空间)
尝试已有数据结构的适用性
数据结构 | 查找复杂度 | 是否支持区间查找 | 适合做索引? |
散列表 | O(1) | ❌ | 否 |
平衡二叉树 | O(logn) | ✅(中序遍历) | 有限制 |
跳表 | O(logn) | ✅ | 可能 |
- 结论:跳表接近满足需求,但数据库索引实际使用的是 B+ 树。
从二叉树演进到 B+ 树的过程
- 改造思路:二叉树节点只做索引,叶子节点串成有序链表以支持区间遍历
- 问题:数据量大时,索引树过高,导致磁盘 I/O 次数增多,查找变慢
- 优化:用多叉树(m 叉树)降低树的高度,减少磁盘 I/O 次数
-
- 例:对一亿条数据,二叉树高度可能高达 26,而 100 叉树高度仅为 3
2.1. B+ 树的结构设计
pytho实现B+树的结构设计:
class BPlusTreeNode:"""B+ 树中的非叶子节点定义"""def __init__(self, m):self.m = m # m 叉树,最大子节点个数self.keywords = [] # 键值列表 (最多 m-1 个)self.children = [] # 子节点指针列表 (最多 m 个)def is_leaf(self):return Falseclass BPlusTreeLeafNode:"""B+ 树中的叶子节点定义"""def __init__(self, k):self.k = k # 每个叶子节点最多存储 k 个键值对self.keywords = [] # 键值列表self.data_addresses = [] # 数据地址(或引用)列表self.prev = None # 前驱叶子节点指针self.next = None # 后继叶子节点指针def is_leaf(self):return True
页大小与分叉因子的关系:
- 操作系统按页(如 4KB)读取数据
- 设计 m时要尽量让一个节点大小 = 一个页大小
不管是内存中的数据,还是磁盘中的数据,操作系统都是按页(一页大小通常是 4KB,这个值可以通过 getconfig PAGE_SIZE 命令查看)来读取的,一次会读一页的数据。如果要读取的数据量超过一页的大小,就会触发多次 IO 操作。所以,我们在选择 m 大小的时候,要尽量让每个节点的大小等于一个页的大小。读取一个节点,只需要一次磁盘 IO 操作。
2.2. 索引影响写入性能
对于一个 B+ 树来说,m 值是根据页的大小事先计算好的,也就是说,每个节点最多只能有 m 个子节点。在往数据库中写入数据的过程中,这样就有可能使索引中某些节点的子节点个数超过 m,这个节点的大小超过了一个页的大小,读取这样一个节点,就会导致多次磁盘 IO 操作。
写入操作(插入/删除)可能触发以下行为:
- 插入时节点分裂(子节点超过 m)
- 删除时节点合并(子节点少于 m/2)
这些过程都需要修改索引树结构,可能层层递归、影响父节点甚至根节点,所以 写入比读取慢。
2.3. 对比与总结
B+ 树 vs 跳表:相似与差异
- 都支持区间查找
- B+ 树是磁盘友好结构,设计重点是降低磁盘 I/O 次数
- 跳表更偏内存优化,适合缓存、高速数据结构
- B+ 树历史更久(1972 年),跳表更现代(1989 年)
B+ 树的特点总结:
特性 | 描述 |
多路搜索树 | 每个节点最多有 m 个子节点,最少 m/2(除根节点) |
只在叶子节点存储数据 | 非叶节点仅作索引 |
所有叶子节点构成双向的有序链表 | 支持高效的区间查找 |
适配磁盘读写(页设计) | 减少磁盘 I/O 次数 |
插入/删除可能引发结构变动 | 分裂/合并机制维护树的平衡 |
B 树 / B-树 与 B+ 树的区别简析:
- B 树(B-Tree):数据存储在所有节点上(非叶节点也存数据)
- B+ 树:数据仅存在叶子节点,非叶节点仅做索引,更适合数据库和文件系统使用
相关文章:
高效查询:位图、B+树
1. 位图(BitMap)与布隆过滤器(Bloom Filter) 1.1. 问题背景与解决方案 问题背景 场景:网页爬虫判重 搜索引擎的爬虫会不断地解析网页中的链接并继续爬取。一个网页可能在多个页面中出现,容易重复爬取。…...
HashMap的扩容机制
在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次每次扩容都是达到了扩容阈值(数组长度 * 0.75) 每次扩容的时候,都是扩容之前容量的2倍; 扩容之后&#…...
从坏道扫描到错误修复:HD Tune实战指南
一、硬盘检测的必要性 随着计算机使用时间的增加,机械硬盘和固态硬盘都会出现不同程度的性能衰减。定期进行硬盘健康检查可以:及时发现潜在故障;预防数据丢失风险;掌握存储设备实际状态。 二、HD Tune功能解析 性能测试&#x…...
Leetcode 3553. Minimum Weighted Subgraph With the Required Paths II
Leetcode 3553. Minimum Weighted Subgraph With the Required Paths II 1. 解题思路2. 代码实现 题目链接:3553. Minimum Weighted Subgraph With the Required Paths II 1. 解题思路 这一题很惭愧,并没有自力搞定,是看了大佬们的解答才有…...
算法加训之最短路 上(dijkstra算法)
目录 P4779 【模板】单源最短路径(标准版)(洛谷) 思路 743. 网络延迟时间(力扣) 思路 1514.概率最大路径(力扣) 思路 1631.最小体力消耗路径 思路 1976. 到达目的地的方案数 …...
01 Nginx安装及基本配置
01 Nginx安装 # 官网:https://nginx.org/en/ # 点击下载图1 Nginx下载官网 # https://nginx.org/en/download.html # 全是各个平台的源码包图2 Nginx下载版本 # 找到最下面的stable and mainline(稳定版和主线版)图3 找到最下面的稳定版 # https://nginx.org/en/li…...
ABP vNext 多租户系统实现登录页自定义 Logo 的最佳实践
🚀 ABP vNext 多租户系统实现登录页自定义 Logo 的最佳实践 🧭 版本信息与运行环境 ABP Framework:v8.1.5.NET SDK:8.0数据库:PostgreSQL(支持 SQLServer、MySQL 等)BLOB 存储:本地…...
Docker 网络
目录 前言 1. Docker 网络模式 2. 默认 bridge 网络详解 (1)特点 (2)操作示例 3. host 网络模式 (1)特点 (2)操作示例 4. overlay…...
btc交易所关键需求区 XBIT反弹与上涨潜力分析
在加密货币市场的浪潮中,狗狗币(DOGE)近期的走势吸引了众多投资者的目光。根据XBIT分析,狗狗币刚刚踏入关键需求区,此前虽从高点大幅下跌了10%,但XBIT去中心化交易所平台分析师认为,短期内它有望…...
深度剖析:YOLOv8融入UNetv2 SDI模块的性能提升之旅
文章目录 一、引言二、SDI多层次特征融合模块概述(一)背景和动机(二)模块设计原理 三、SDI模块实现(一)关键代码结构(二)代码解析 四、将SDI模块融入YOLOv8(一࿰…...
图像定制大一统?字节提出DreamO,支持人物生成、 ID保持、虚拟试穿、风格迁移等多项任务,有效解决多泛化性冲突。
字节提出了一个统一的图像定制框架DreamO,支持人物生成、 ID保持、虚拟试穿、风格迁移等多项任务,不仅在广泛的图像定制场景中取得了高质量的结果,而且在适应多条件场景方面也表现出很强的灵活性。现在已经可以支持消费级 GPU(16G…...
spark数据处理练习题详解【下】
12. (单选题) def main(args: Array[String]): Unit { println(func1("张三",f1)) } def func1(name:String,fp:(________________)): String { fp(name) } def f1(s:String): String { "welcome "s } 选择填空() A.String>S…...
Vue基础(11)_条件渲染
原生css想让显示的元素隐藏,方式有以下几点: display: none; opacity: 0; visibility: hidden; 那么vue中是怎样实现元素显示/隐藏的呢? 条件渲染 v-show 写法:v-show"表达式" 判断:表达式转换为布尔值(tr…...
湖北理元理律师事务所:债务优化服务的四维创新实践
在债务问题普遍影响家庭经济稳定的当下,专业法律服务机构的价值不仅在于提供解决方案,更需构建可持续的服务生态。湖北理元理律师事务所通过“法律心理技术教育”四维服务体系,探索出一条兼顾债务化解与生活质量保障的创新路径。 服务模式创…...
ubuntu工控机固定设备usb串口号
ubuntu工控机固定设备usb串口号 1、多个USB设备的ID相同 ubuntu系统中的串口使用权限并没有对所有的用户进行开放,所以在使用代码对串口进行操作时,需要打开用户对串口的使用权限,否则在代码中会出现“串口无法打开的报错”,只有…...
MongoDB的安装及简单使用
MongoDB 是一个开源的文档型 NoSQL 数据库,由 MongoDB Inc. 开发,专为灵活性和可扩展性设计。 特点: 1.文档模型:数据以 BSON(二进制 JSON)格式存储,支持嵌套结构。 2.动态 S…...
卷积神经网络进阶:转置卷积与棋盘效应详解
【内容摘要】 本文深入解析卷积神经网络中的转置卷积(反卷积)技术,重点阐述标准卷积与转置卷积的计算过程、转置卷积的上采样作用,以及其常见问题——棋盘效应的产生原因与解决方法,为图像分割、超分辨率等任务提供理论…...
Linux进程信号(三)之信号产生2
文章目录 4. 由软件条件产生信号5. 硬件异常产生信号模拟一下除0错误和野指针异常除0错误野指针错误 总结思考一下 4. 由软件条件产生信号 SIGPIPE是一种由软件条件产生的信号,在“管道”中已经介绍过了。 软件条件不就绪,很明显这个软件条件没有直接报错ÿ…...
【AWS入门】Amazon SageMaker简介
【AWS入门】Amazon SageMaker简介 [AWS Essentials] Brief Introduction to Amazon SageMaker By JacksonML 机器学习(Machine Learning,简称ML) 是当代流行的计算机科学分支技术。通常,人们在本地部署搭建环境,以满足机器学习的要求。 AWS…...
MySQL--day2--基本的select语句
(以下内容全部来自上述课程) SQL概述 结构化查询语句 1. SQL分类 DDL:数据定义(definition)语言:create、drop、alter… DML:数据操作(manipulation)语言ÿ…...
程序代码篇---python获取http界面上按钮或者数据输入
文章目录 前言 前言 本文简单接受了python获取http界面上按钮或者数据输入...
网络安全利器:蜜罐技术详解
蜜罐是网络安全领域中一种主动防御和情报收集的重要工具。本文将深入探讨蜜罐技术的原理、类型、应用场景以及部署注意事项。 1. 什么是蜜罐? 蜜罐(Honeypot)是一种安全资源,其价值在于被探测、攻击或未经授权使用。简单来说,蜜罐就是一个诱饵系统,用来吸引黑客的注意力…...
回溯实战篇3
文章目录 前言排列全排列全排列II 棋盘问题N皇后解数独 其他递增子序列重新安排行程 前言 今天继续带大家进行回溯的实战篇3,去学习如何用回溯的方法去解决排列和棋盘以及其他用回溯方法解决的问题,最重要的就是学会回溯三部曲的构建,一文带…...
Spark 基础自定义分区器
(一)什么是分区 【复习提问:RDD的定义是什么?】 在 Spark 里,弹性分布式数据集(RDD)是核心的数据抽象,它是不可变的、可分区的、里面的元素并行计算的集合。 在 Spark 中…...
【提高+/省选−】洛谷P1495 —— 【模板】中国剩余定理(CRT)/ 曹冲养猪
见:P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪 - 洛谷 题目描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎&a…...
系统架构设计师考前冲刺笔记-第1章-系统工程与信息系统基础
文章目录 第1章 系统工程与信息系统基础大纲13 DSS5678 BSP910 SCM11 OLAP12 OLAP14 BRP15 集成16 企业门户19 边缘计算 第1章 系统工程与信息系统基础 大纲 1 3 DSS DSS 决策支持系统 Decision Support System 5 6 7 8 BSP 9 10 SCM 注意:生产计划 11 OLAP O…...
Vue环境下数据导出Excel的全面指南
文章目录 1. 前言2. 原生JavaScript实现方案2.1 使用Blob对象和URL.createObjectURL2.2 使用Base64编码实现 3. 常用第三方库方案3.1 使用SheetJS (xlsx)3.2 使用ExcelJS3.3 使用vue-json-excel 4. 服务器端导出方案4.1 前端请求服务器生成Excel4.2 使用Web Worker处理大数据导…...
Linux下 使用 SSH 完成 Git 绑定 GitHub
文章目录 1、检查 SSH2、生成 SSH key3、添加 SSH key4、验证绑定是否成功 1、检查 SSH Git Bash 中输入ssh命令,查看本机是否安装 SSH: 2、生成 SSH key (1)输入 ssh-keygen -t rsa 命令,表示我们指定 RSA 算法生…...
Jsoup库和Apache HttpClient库有什么区别?
Jsoup 和 Apache HttpClient 是两个功能不同的库,它们在 Java 开发中被广泛使用,但用途和功能有明显的区别: Jsoup 用途:Jsoup 是一个用于解析 HTML 文档的库。它提供了非常方便的方法来抓取和解析网页内容,提取和操作…...
安全漏洞频发,如何加强防护措施?
当系统安全漏洞频发时,应从代码安全审查、自动化漏洞扫描、权限控制与访问管理、员工安全意识培训等四个关键维度加强防护。其中,代码安全审查是防止漏洞渗透的第一道防线。企业应将代码安全审查纳入CI/CD流程,实施静态代码分析和依赖包检查机…...
Text models —— BERT,RoBERTa, BERTweet,LLama
BERT 什么是BERT? BERT,全称Bidirectional Encoder Representations from Transformers,BERT是基于Transformer的Encoder(编码器)结构得来的,因此核心与Transformer一致,都是注意力机制。这种…...
CodeBuddy初探
回顾Trae 上一篇博客Trae IDE和VSCode Trae插件初探-CSDN博客,我们进行了TraeIDE和Trae插件初探,给了Trae这样一个任务: 生成一个to do list清单web页面,采用vue实现,可以在页面上进行todolist进行增删改查。 Trae的…...
spark数据处理练习题详解【上】
1. (单选题) scala中属于序列的可变的集合,可以添加,删除元素的是() A.Array B.List C.Tuple D.ListBuffer 答案及解析:D 在Scala中,属于序列的可变集合,可以添加和删除元素的是ÿ…...
sparkSQL读入csv文件写入mysql(2)
(二)创建数据库和表 接下来,我们去创建一个新的数据库,数据表,并插入一条数据。 -- 创建数据库 CREATE DATABASE spark; -- 使用数据库 USE spark;-- 创建表 create table person(id int, name char(20), age int);-- …...
产品周围的几面墙
不能把排序,当单选题做。 2025年的杭州咖啡馆,味道最浓的不是咖啡,是聊各种项目和创业的卷味。 在过去几年,聊项目的也不少,那时候带着更加浓烈的自信和松弛感,不过今年略带几分忐忑和试探的口吻。 看到网…...
【锂电池剩余寿命预测】LSTM长短期记忆神经网络锂电池剩余寿命预测(Pytorch完整源码和数据)
目录 效果一览程序获取程序内容代码分享效果一览 程序获取 获取方式一:文章顶部资源处直接下载:...
螺旋矩阵--LeetCode
题目 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入:matrix [[…...
湖北理元理律师事务所:债务管理的社会价值探索
债务问题从来不是孤立的经济事件,其背后牵涉家庭稳定、社会信用体系乃至区域经济发展。湖北理元理律师事务所通过五年服务数据发现:科学债务规划可使单个家庭挽回约23%的可支配收入,间接降低离婚率、心理健康问题发生率等社会成本。 债务优化…...
知识图谱(KG)与大语言模型(LLM)
知识图谱(KG)以其结构化的知识表示和推理能力,为大语言模型(LLM)的“幻觉”、知识更新滞后和可解释性不足等问题提供了有力的解决方案。反过来,LLM的强大文本理解和生成能力也为KG的构建、补全、查询和应用…...
LLM大语言模型系列1-token
一,什么是token 1,什么是token: 参考:https://en.wikipedia.org/wiki/Token https://en.wikipedia.org/wiki/Lexical_analysis#Token 我们有很多描述token的解释,建议是汇总在一起进行综合理解: 1️⃣To…...
数据清洗-案例
四)实现代码 在之前的项目的基础之上,重写去写一个包,并创建两个类:WebLogMapper和WebLogDriver类。 (1)编写WebLogMapper类 package com.root.mapreduce.weblog; import java.io.IOException; import…...
项目的部署发布和访问的流程
首先打包项目: npm run build 打包后的文件会生成在dist文件夹中,将dist文件夹需要放到服务器里面,意味着服务有dist静态资源(index.html,css/,js/,img/) 用户在浏览器输入域名&am…...
人工智能、机器学习、深度学习定义与联系
人工智能、机器学习、深度学习定义与联系目录 一、人工智能(Artificial Intelligence, AI)1、定义2、特征:3、关键阶段的概述:1. 萌芽期(1940s–1950s):理论奠基2. 形成期(1950s–19…...
Gartner《如何将生成式人工智能(GenAI)集成到应用架构》学习心得
针对软件架构师、技术专业人士如何更好的把 GenAI 如何融入解决方案,提升用户体验、生产力并带来差异化成果的趋势,Gartner发布了《Integrating GenAI Into Your Application Architecture》研究报告。 报告首先介绍了 GenAI 的发展背景,指出其已成为主流趋势,大型语言模型…...
vscode中Debug c++
在vscode中Debug ros c程序 1 在Debug模式下编译 如果用命令行catkin_make,在输入catkin_make时加上一个参数: catkin_make -DCMAKE_BUILD_TYPEDebug 或者直接修改CMakelist.txt,添加以下代码: SET(CMAKE_BUILD_TYPE "D…...
c++从入门到精通(六)--特殊工具与技术-完结篇
特殊工具与技术-完结篇 控制内存分配 重载new和delete: 如果应用程序希望控制内存分配的过程,则它们需要定义自己的operator new函数和operator delete函数。当自定义了全局的operator new函数和operator delete函数后,我们就担负起了控…...
原型链的详细解释及使用场景
一、原型链的概念 原型链是JavaScript实现继承和属性共享的核心机制。每个对象都有一个内部属性[[Prototype]](可通过proto访问),指向其原型对象。当访问对象的属性时,若对象自身不存在该属性,则会沿着原型链向上查找…...
OpenCL C C++核心对象与属性对比
基础对象对应关系 OpenCL C 对象OpenCL C 对应类型创建函数示例cl::Platformcl_platform_idclGetPlatformIDs(1, &platform, NULL)cl::Devicecl_device_idclGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL)cl::Contextcl_contextclCreateContext(NULL,…...
Azure 机器学习初学者指南
Azure 机器学习初学者指南 在我们的初学者指南中探索Azure机器学习,了解如何设置、部署模型以及在Azure生态系统中使用AutoML & ML Studio。Azure 机器学习 (Azure ML) 是一项全面的云服务,专为机器学习项目生命周期而设计&am…...
一文读懂----Docker 常用命令
Docker 是一个强大的容器化平台,广泛用于开发、测试和生产环境。通过 Docker 命令行工具(CLI),我们可以轻松管理容器、镜像、网络和卷等资源。本文将详细介绍 Docker 的常用命令,带你熟练掌握 Docker 的核心操作命令。…...