RoaringBitMap处理海量数据内存diff

一、背景

  假设mysql库中有一张近千万的客户信息表(未分表),其中有客户性别,等级(10个等级),参与某某活动等字段
 1、如果要通过等级+性别+其他条件(离散度也低)筛选出客户,如何处理查询?
 2、参与活动是记录活动ID,客户每参与一个活动,就要记录客户和该活动id的关联,活动记录字段如何存储?
使用mysql存储,对应上方场景,可能会面临以下问题
 1、查询条件关联字段虽然建立了索引,但是由于字段值离散度较低,导致索引失效,直接变成全表扫描
 2、活动记录字段,由于要存储多值,只能设计存活动ID的json串或者符号分隔存储,直接导致该字段无法建立有效的索引
  可以发现,传统的关系型数据库,面对以上场景,暂时没办法设计出合理的索引,所以会导致无法查询的情况。
  为了解决以上问题,一开始方向也是使用mongoDB或者ES去进行数据异构存储,借助NoSql的结构,存储频繁变更的数据,比如,活动id字段可以直接存储为数组,也可以建立索引。
但是,由于时间、资源等关系,进行数据异构存储成本较大,所以只能寻找替代方案。

  在存储方式还是使用Mysql的情况下,如何进行数据检索呢,基于上面的场景,很明显直接使用mysql查询已经走不通了,需要使用标签操作数据,在内存中进行数据的交并集操作。

  所以问题就转变成了,什么样的数据结构,可以以较低的内存占用,存储海量数据,还支持交差并集等逻辑操作呢?

位图结构,完美适合标签场景,位图是过bit数组来存储数据的数据结构,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。通过最小的单位bit来进行0|1的设置,表示某个元素的值或者状态,时间复杂度为O(1)。

二、技术选型

接上背景,既然选择了位图作为标签场景下的查询方案,那么应该选取哪种Bitmap实现呢?

java原生的BitSet,guava的EWAHCompressedBitmap,第三方的RoaingBitmap  

  注:由于标签可能每日全量更新,需要考虑内存操作且能够持久化,redis的Bitmap,在一亿数据量情况下,不拆分(取余,hash等),size为12M,推算5千万数据量size为6M,属于大key( >5M ),且大数据量Bitmap初始化,可能造成redis阻塞延迟,故暂时不考虑。

巧用RoaringBitMap处理海量数据内存diff问题 - 知乎

这里借用上方引文的测试结果:

内存占用测试:往Bitmap中添加1、N+1、2N+1.....5000000数据,其中N为数据的步长(稀疏度) 来计算各个Bitmap在不同稀疏度下(N)的内存占用情况。通过下图可以看出,除了在稀疏度为1时,EWAHCompressedBitmap内存占用最低以外,其余稀疏度下的内存占用:RoaingBitmap<EWAHCompressedBitmap<BitSet。

CPU耗时测试:往各个Bitmap中添加1、N+1、2N+1.....5000000数据,其中N为数据的步长(稀疏度),然后与有5000000满数据的Bitmap分别求2000次差集并取2000次中的最大耗时,得到在每个稀疏度下每种Bitmap的耗时情况。通过下图可以看出,各个稀疏度下的cpu耗时:RoaingBitmap≈EWAHCompressedBitmap<BitSet.

基于上方的测试数据,从内存占用,CPU耗时等方面,RoaingBitmap均要优于其他类型的位图,所以,选择RoaingBitmap作为新方案的Bitmap实现。

持久化存储:Bitmap、BitSet、RoaringBitmap持久化存储_bitset持久化-CSDN博客

api文档:RoaringBitmap 1.0.1 javadoc (org.roaringbitmap)

三、RoaingBitmap简单介绍及原理

如果你只是简单使用,那么记住:RoaringBitmap是高效压缩位图。其实就够了。

  RoaringBitmap的核心思想是将整数集合按照高位划分成不同的容器,每个容器内部再使用不同的存储策略。具体而言,它将一个32位的整数分成两部分:

1、高16位作为容器的索引(container index)。
2、低16位则存储在相应的容器中。
RoaringBitmap支持两种类型的容器:

1、ArrayContainer:当一个容器内的元素数量较少(通常少于4096个)时,使用一个简单的数组来存储这些元素。这种容器适合存储稀疏的数据。
2、BitmapContainer:当容器内元素数量较多时,使用位图存储。位图是一个长数组,每个位代表一个低16位的整数是否存在。这适合存储密集型数据。

传送门:RoaringBitmap的原理与应用,看这个就够了-CSDN博客

四、存储设计

  使用Mysql的longtext类型存储持久化后的RoaingBitmap。

注意:

1、Mysql字段类型:text 字段类型的字节限制为 65535 字节, 约为0.06MB;longtext 字段类型的字节限制为 2147483647 字节,约为2047MB;mediumtext 字段类型的字节限制为 16777215 字节,约为16MB。

2、mysql单次最大传输数据量限制约为16M

3、RoatingBitMap 5千万全量数据,持久化存储需要 6259385 字节,约 6M;

持久化关联Java代码,以及RoaringBitMap的逻辑i操作:

    /**
     * roaringBitmap 转 string
     *
     * @param roaringBitmap 入参
     * @return str
     */
    public static String roaringBitMapToString(RoaringBitmap roaringBitmap) {
        // RoaringBitMap 转为byte数组
        byte[] array = new byte[roaringBitmap.serializedSizeInBytes()];
        roaringBitmap.serialize(ByteBuffer.wrap(array));
        // byte转为字符串
        return new String(array, StandardCharsets.ISO_8859_1);
    }

    /**
     * string 转 roaringBitmap
     *
     * @param bitMapStr bitmap序列化字符串
     * @return RoaringBitmap
     */
    public static RoaringBitmap stringToRoaringBitMap(String bitMapStr) {
        RoaringBitmap roaringBitmap = new RoaringBitmap();
        try {
            // str 转为 byte数组
            byte[] redisArray = bitMapStr.getBytes(StandardCharsets.ISO_8859_1);
            roaringBitmap.deserialize(ByteBuffer.wrap(redisArray));
        } catch (IOException e) {
            log.error("stringToRoaringBitMap {} Error", bitMapStr.length(), e);
        }
        return roaringBitmap;
    }

    /**
     * bitMap操作
     *
     * @param oldBitMap    bitMap_1
     * @param newSubBitMap bitMap_2
     * @param operate      操作符
     * @return RoaringBitmap
     */
    public static RoaringBitmap roaringBitMapOperate(
            RoaringBitmap oldBitMap, RoaringBitmap newSubBitMap, String operate) {
        switch (operate) {
            case "add":
            case "or":
                oldBitMap.or(newSubBitMap);
                break;
            case "remove":
                oldBitMap.andNot(newSubBitMap);
                break;
            case "replace":
                oldBitMap = newSubBitMap;
                break;
            case "and":
                oldBitMap.and(newSubBitMap);
                break;
            default:
                throw new IllegalArgumentException("operate 异常" + operate);
        }
        return oldBitMap;
    }

五、压测数据准备

目标数据量 五千万 客户,10个标签,总数据量在一亿两千万左右,存储空间53MB

六、本地环境(4核8G机器)测试结果

5千万客户,标签覆盖率约为 50%,40%,30% ,20%,10%五个批次;客户随机离散分布在10个标签, 单标签平均客户量一千二百万左右,测试随机取交,并集耗时。

jmeter单线程循环调用

参与筛选标签数据

交/并集

取样次数

响应耗时中位数

平均数

响应耗时90%

响应耗时95%

响应耗时99%

最小

最大

2个50277276286289303263303
2个50273276286288308262308
2个随机50282283299302307265307
5个50702712746755792664792
5个50701710727733761667761
5个随机50685690715729742665742
8个随机501145114011751187120210751202
10个随机501379138714331450148113361481

jmeter多线程循环调用 开发环境单副本 5个线程循环20次

参与筛选标签数据

交/并集

取样次数

响应耗时中位数

平均数

响应耗时90%

响应耗时95%

响应耗时99%

最小

最大

2个随机100526525601609623299658
5个随机100140914481685172318168711897
8个随机1002210221924332468260516502760
10个随机1002789281530943125330821943440

1、任意2个标签取交、并集耗时, 各采样50次

并集测试结果

2、任意5个标签取交、并集耗时, 各采样50次

交集测试结果

3、任意8个标签随机交、并集耗时, 采样50次

4、任意10个标签随机取交、并集耗时, 各采样50次

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/721479.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NVIDIA新模型Nemotron-4:98%的训练数据是合成生成的,你敢信?

获取本文论文原文PDF&#xff0c;请公众号 AI论文解读 留言&#xff1a;论文解读 标题&#xff1a;Nemotron-4 340B Technical Report 模型概述&#xff1a;Nemotron-4 340B系列模型的基本构成 Nemotron-4 340B系列模型包括三个主要版本&#xff1a;Nemotron-4-340B-Base、…

RNN的变种们:GRULSTM双向RNN

上篇笔记记录到RNN的一个缺点&#xff1a;训练时会出现梯度消失&#xff0c;解决的办法是找到一个更优的计算单元。这里也有GRU和LSTM。 GRU&#xff08;Gated Recurrent Unit&#xff09;门控训练网络 什么是门控机制&#xff1f;就是对当前的输入进行一个筛选。门打开&…

《UNIX环境高级编程》第三版(电子工业出版社出品)——两年磨一剑的匠心译作

历时两年&#xff0c;《UNIX环境高级编程》的翻译工作终于落下帷幕。这一路走来&#xff0c;真可谓是如鱼饮水&#xff0c;冷暖自知。还记得最初看到招募译者消息的那一刻&#xff0c;内心的激动难以言表。我毫不犹豫地报名&#xff0c;而后经历了试译、海选等激烈的角逐&#…

「TCP 重要机制」滑动窗口 粘包问题 异常情况处理

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;计网 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 滑动窗口&粘包问题&异常情况处理 &#x1f349;滑动窗口&#x1f34c;流量控制&#x1f34c;拥塞控制&#x1f34c;延时应答&…

mkv文件怎么转成mp4?教你四种常见的转换方法!

mkv文件怎么转成mp4&#xff1f;大家在使用mkv文件的时候有没有遇到过下面这些缺点&#xff0c;首先是mkv的兼容性不行&#xff0c;这体验在它不方便分享上面&#xff0c;很有可能我们分享出去但是对方根本无法进行接受&#xff0c;这就导致我们需要进行额外的操作才能分享&…

轻轻松松上手的LangChain学习说明书

本文为笔者学习LangChain时对官方文档以及一系列资料进行一些总结&#xff5e;覆盖对Langchain的核心六大模块的理解与核心使用方法&#xff0c;全文篇幅较长&#xff0c;共计50000字&#xff0c;可先码住辅助用于学习Langchain。 一、Langchain是什么&#xff1f; 如今各类AI…

pip导出格式错乱问题

pip导出带有各种路径 pip只导出版本 pip list | tail -n 3 | awk {print $1""$2} > requirements.txt

kettle从入门到精通 第七十一课 ETL之kettle 再谈http post,轻松掌握body中传递json参数

场景&#xff1a; kettle中http post步骤如何发送http请求且传递body参数&#xff1f; 解决方案&#xff1a; http post步骤中直接设置Request entity field字段即可。 1、手边没有现成的post接口&#xff0c;索性用python搭建一个简单的接口&#xff0c;关键代码如下&#…

6-18作业

作业1&#xff1a; mywidget.h #ifndef MYWIDGET_H #define MYWIDGET_H#include <QWidget> #include <QLabel> #include <QMessageBox>QT_BEGIN_NAMESPACE namespace Ui { class myWidget; } QT_END_NAMESPACEclass myWidget : public QWidget {Q_OBJECTpu…

Oracle基本语法

前言&#xff1a; 1.使用的数据库不同&#xff0c;所使用的语法也略有不同 2.SQL对大小写不敏感&#xff0c;无论大小写&#xff0c;sql自动转换为大写 3.用户名、表名、表空间名、文件路径......等需要用单引号将其包含 4.一般引号里面的内容需要大写 准备工作&#xff1a; &a…

NocoBase调研

项目概述&#xff1a; nocobase是一个开源的无代码和低代码开发平台&#xff0c;允许用户快速部署私有、可控、易于扩展的系统。 NocoBase官网&#xff1a;NocoBase-开源、私有部署的轻量级无代码和低代码开发平台 核心特性&#xff1a; 强调NocoBase的数据模型驱动方法&am…

淘宝文件系统-哈希查找分析

一.框架理解 在淘宝文件系统中&#xff0c;通常会将文件索引存储在一块内存中&#xff0c;这块内存包含了若干个主块&#xff08;Index Block&#xff09;。每个主块中存储着多个文件的索引信息。每个文件的索引按照哈希表的形式进行存储&#xff0c;通过哈希值来定位到具体的文…

铠侠全面复产:NAND价格还会涨吗?

近期&#xff0c;日本经济新闻&#xff08;Nikkei&#xff09;报道指出&#xff0c;经历长达20个月的产能削减后&#xff0c;全球第四大三维NAND闪存制造商铠侠已全面恢复生产。这一转变不仅标志着铠侠再次全力投入到市场份额的争夺中&#xff0c;也可能预示着闪存市场价格即将…

不重新安装Anaconda找回不见的Anaconda Prompt

找回Anaconda Prompt只需三步 系统&#xff1a;win11 x641.cd Anaconda的安装目录2. Anaconda Prompt又回来了 系统&#xff1a;win11 x64 1.cd Anaconda的安装目录 winR 输入cmd 进入命令行&#xff0c;进入到Anaconda的安装目录 eg&#xff1a;我的Anaconda安装在&#xff…

多规格产品应该如何设置呢?

今天一用户从供应商手中拿到产品价目表&#xff0c;但是设置起来蒙圈了&#xff0c;接下来我们就一起设置一下吧&#xff5e; 一、产品价格表 我们通过供应商手中拿到产品价目表是这个样子的&#xff1a; 我们可以看到此产品的销售客价根据不同地区导致的价格不同&#xff0c;…

Nvidia Isaac Sim 入门教程 2024(2)安装与配置

Isaac Sim 安装与环境配置 版权信息 Copyright 2023-2024 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The a…

Git快速上手

初识Git 是一个免费开源, 分布式的代码版本控制系统, 帮助开发团队维护代码 作用: 记录代码内容,切换代码版本,多人开发时高效合并代码内容 Git和GitHub Git是一个软件, Github是一个网站,两者的功能都是提供版本控制服务. 官网: GitHub: Let’s build from here GitHub …

【多模态大模型教程】在自定义数据上使用Qwen-VL多模态大模型的微调与部署指南

Qwen-VL 是阿里云研发的大规模视觉语言模型&#xff08;Large Vision Language Model, LVLM&#xff09;。Qwen-VL 可以以图像、文本、检测框作为输入&#xff0c;并以文本和检测框作为输出。 Qwen-VL-Chat 大语言模型(Qwen-7B) 视觉图片特征编码器(Openclip ViT-bigG) 位置…

工业物联网关为智能制造业提供哪些支撑?天拓四方

随着科技的飞速发展&#xff0c;智能制造业已成为工业领域的转型方向。在这一转变中&#xff0c;工业物联网关发挥着至关重要的作用。作为连接物理世界与数字世界的桥梁&#xff0c;工业物联网关不仅实现了设备与设备、设备与云平台之间的互联互通&#xff0c;更通过实时数据采…

Spring AOP 基于注解实现用户权限校验

主要注解 interface&#xff1a;继承了 Annotation 接口的自定义注解&#xff0c;定义注释类型。 Target&#xff1a;表示这个注解可以应用的地方&#xff0c;此处做权限校验是用在方法上的&#xff0c;所以此处的值为 Target(ElementType.METHOD) …