
https://m.toutiao.com/is/i8UekRdk/ 炒股配资门户
Bitmap为解决海量数据处理问题而生,本文从Bitmap的由来、原理、优缺点、扩展、应用及面试等六类视角(细分十一小节)展开讲解。
一 为什么会发明Bitmap在计算机科学中,处理大规模数据时,传统的数据结构和算法往往会遇到性能瓶颈。例如,当需要在大量整数中查找、去重或进行其他操作时,常规方法可能需要大量的内存和计算资源。
为了解决这个问题,研究者们开始寻找更高效的数据结构。他们发现,如果使用位(bit)来表示数据,可以极大地节省内存空间。这是因为一个位只有0和1两种状态,相比于使用字节或更大的单位来存储数据,位操作更加高效。
基于上述思路,John W. Tukey在1948年发明了Bitmap。Bitmap是一种特殊的数组,它的每个元素都可以表示为一个位。通过使用位运算,可以对Bitmap进行高效的操作,如设置、清除和检测某个位的状态。
二 Bitmap详解Bitmap 的基本原理就是用一个 bit 来标记某个元素对应的 Value,而 Key 即是该元素。由于采用一 个bit 来存储一个数据,因此可以大大的节省空间。
我们通过一个具体的例子来说明 Bitmap 的原理,假设我们要对 0-31 内的 3 个元素 (10, 17,28) 排序,那么我们就可以采用 Bitmap 方法(假设这些元素没有重复)。
如下图,要表示 32 个数,我们就只需要 32 个 bit(4Bytes),首先我们开辟 4Byte 的空间,将这些空间的所有 bit 位都置为 0。
图片
然后,我们要添加(10, 17,28) 这三个数到 BitMap 中,需要的操作就是在相应的位置上将0置为1即可。如下图,比如现在要插入 10 这个元素,只需要将蓝色的那一位变为1即可。
图片
将这些数据插入后,假设我们想对数据进行排序或者检索数据是否存在,就可以依次遍历这个数据结构,碰到位为 1 的情况,就当这个数据存在。
Bitmap 也可以用来表述字符串类型的数据,但是需要有一层Hash映射,如下图,通过一层映射关系,可以表述字符串是否存在。
图片
代码实现方面,可陈述如下:
第一步:构建特定长度的byte数组(new byte[capacity/8 + 1]),其中capacity为整数数组长度(如:10亿个数字等)
byte[] bits = new byte[getIndex(n) + 1];第二步:计算数字num在byte[]中的位置(num/8和num >> 3一样),也就是说num在byte[k],算这个k是几
public int getIndex(int num){ return num >> 3;}第三步:计算数字num在byte[index]中的位置,就是在byte[index]的第几位,每个byte有8位(num % 8)
public int getPosition(int num){ return num & 0x07;}第四步:将所在位置从0变成1,其它位置不变
public void add(byte[] bits, int num){ bits[getIndex(num)] |= 1 << getPosition(num);}第五步:判断指定数字num是否存在
public boolean contains(byte[] bits, int num){ return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;}第六步:重置某一数字对应在bitmap中的值
public void clear(byte[] bits, int num){ bits[getIndex(num)] &= ~(1 << getPosition(num));}三 Bitmap优缺点优点
运算效率高:Bitmap算法利用位运算进行操作,计算机处理位运算的速度非常快,因此Bitmap算法具有很高的运算效率。内存占用少:Bitmap算法以bit为单位存储数据,相比其他数据结构(如数组、链表等),可以极大地节省内存空间。例如,如果需要记录一千万个不同的整数,只需要占用内存为N/8=1250000Bytes=1.192Mb,这对于大数据处理来说是一个很大的优势。缺点
数据密集才有优势:只有当数据比较密集时,Bitmap算法才有优势。如果数据非常稀疏,例如几千个数分布在1~20亿之间,那么占用的空间就会很大,遍历的次数也多,此时使用Bitmap算法可能并不高效。数据不能重复:Bitmap算法的一个主要缺点是它不能处理重复的数据。因为每个bit只能表示0或1两种状态,所以无法对重复的数据进行排序和查找。无法直接对位操作:在Bitmap中,我们不能直接对某一位进行操作,而需要通过计算得到该位的位置,这可能会增加一些计算的复杂性。四 Bitmap的扩展--Roaring Bitmap针对Bitmap的缺点1(数据稀疏时占用内存空间大),S. Chambi、D. Lemire、O. Kaser等人在2016年发表的论文《Better bitmap performance with Roaring bitmaps》 《Consistently faster and smaller compressed bitmaps with Roaring》中提出了RoaringBitMap,一种高效压缩位图,简称RBM。
实现思路
RBM主要将32位的整型(int)分为高16位和低16位(两个short),其中高16位对应的数字使用16位整型有序数组存储,低16位根据不同的情况选择三种不同的container来存储,这三种container分别为:
1 Array Container
底层数据结构为short类型的数组,直接将数字低16位的值存储到该数组中。short类型的数组始终保持有序,方便使用二分查找,且不会存储重复数值。因为这种Container存储数据没有任何压缩,因此只适合存储少量数据。其内部数组容量是动态变化的,当容量不够时会进行扩容,最大容量为4096。由于数组是有序的,存储和查询时都可以通过二分查找快速定位其在数组中的位置。
ArrayContainer占用的空间大小与存储的数据量为线性关系,每个short为2字节,因此存储了N个数据的ArrayContainer占用空间大致为2N字节。存储一个数据占用2字节,存储4096个数据占用8kb。
图片
2 Bitmap Container
底层实现为位图。这种Container使用long[]存储位图数据。我们知道,每个Container处理16位整形的数据,也就是0~65535,因此根据位图的原理,需要65536个比特来存储数据,每个比特位用1来表示有,0来表示无。每个long有64位,因此需要1024个long来提供65536个比特。
因此,每个BitmapContainer在构建时就会初始化长度为1024的long[]。这就意味着,不管一个BitmapContainer中只存储了1个数据还是存储了65536个数据,占用的空间都是同样的8kb。
图片
3 Run Container
RunContainer中的Run指的是行程长度压缩算法(Run Length Encoding),对连续数据有比较好的压缩效果。它的原理是,对于连续出现的数字,只记录初始数字和后续数量。即:
对于数列11,它会压缩为11,0;对于数列11,12,13,14,15,它会压缩为11,4;对于数列11,12,13,14,15,21,22,它会压缩为11,4,21,1;源码中的short[] valueslength中存储的就是压缩后的数据。
这种压缩算法的性能和数据的连续性(紧凑性)关系极为密切,对于连续的100个short,它能从200字节压缩为4字节,但对于完全不连续的100个short,编码完之后反而会从200字节变为400字节。
也就RBM在存入一个32位的整形数字时,会先按照该数字的高16位进行分桶,以确定该数字要存入到哪个桶中。确定好分桶位置后,再将该数字对应的低16位放入到当前桶所对应的container中。
图片
举个栗子
以十进制数字131122为例,现在我们要将该数字放入到RBM中。第一步,先将该数字转换为16进制,131122对应的十六进制为0x00020032;其中,高十六位对应0x0002,首先我们找到0x0002所在的桶,再将131122的低16位存入到对应的container中,131122的低16位转换为10进制就是50,没有超过ArrayContainer的容量4096,所以将低16位直接放入到对应的ArrayContainer中。
图片
如果要插入的数字低16位超过了4096,RBM会将ArrayContainer转换为BitMapContainer。反之,如果数据在删除之后,数组中的最大数据小于4096,RBM会将BitMapContainer转换回ArrayContainer。
图片
RBM处理的是32位的数字,如果我们想处理Long类型的数字怎么办呢?这个时候可以使用Roaring64NavigableMap。Roaring64NavigableMap也是使用拆分模式,将一个long类型数据,拆分为高32位与低32位,高32位代表索引,低32位存储到对应RoaringBitmap中,其内部是一个TreeMap类型的结构,会按照signed或者unsigned进行排序,key代表高32位,value代表对应的RoaringBitmap。
空间占用对比
数据类型
操作
Bitmap内存(byte)
RoaringBitmap(byte)
连续数据
插入1000w条连续数据
10000000
1253690
稀疏数据
插入1和999w两个数据
10000000
24
五 Bitmap的扩展--Bloom Filter针对Bitmap的缺点2(数据不能重复),Burton Howard Bloom在1970年他发表的论文《Space/Time Trade-offs in Hash Coding with Allowable Errors》中提出了Bloom Filter。
Bloom Filter:由只存0或1的位数组和多个hash算法, 进行判断数据一定不存在或者可能存在的算法;如果这些bit数组 有任何一个0,则被判定的元素一定不在; 如果都是1则被检元素很可能在;对比bitmap位图,布隆过滤器适合更多类型元素,通过hash值转换。
图片
每次处理元素时,
将元素添加到一个bitmap数组中,每个散列函数将元素映射到bitmap数组中的一个位置如果该位置已经被占用,则将该位置置为1,否则置为0当要查询一个元素是否存在时,只需要计算该元素的散列值,并检查bitmap数组中对应的位置是否已经被置为1如果都是1,则该元素可能存在,否则肯定不存在。优点:占用空间小,查询速度快,空间效率和查询时间都远远超过一般的算法
缺点:有一定的误识别率,有一定的误识别率,即某个元素可能存在,但实际上并不存在;删除困难,因为无法确定某个位置是由哪个元素映射而来的
图片
图片
六 Bitmap的应用--Redis图片
统计当日活跃用户
每日活跃统计创建一个bitmap键,当用户活跃了根据用户id的偏移量来设置对应的位为1
用户签到
每个用户创建一个位图的键,以某一天为基础,之后的天数距离这一天的天数为偏移量,如果用户点击了签到,则设置对用的偏移位为1。
应对缓存穿透问题
举例:比如爬虫服务器在爬取电商网站的商品信息时,首先经过缓存,如果缓存查不到,再去数据库获取信息,因为爬虫的效率很高,且sku很有可能是不存在或者已下架的,就会造成缓存穿透,大量请求被发送到数据库,导致服务器受到影响。
此时,可以在缓存层之前,添加一个布隆过滤器,布隆 过滤器看作是一个bitmap,sku作为offset值,如果商品真实存在,bit值设为1。首先将商品数据初始化,当有请求时,通过getbit判断sku是否有效。如果布隆过滤器认为商品不存在,就拒绝访问,这样就可以保护存储层。
七 Bitmap的应用--阿里Hologres技术平台基于RoaringBitmap的画像分析使用实践,技术用户画像分析是对一个或多个指定用户群,通过可视化的方式,可以多维、立体的展示用户群的画像信息,让运营更好的理解人群,实现人群细分及对个性化运营策略的制定提供能力支撑;在进行数据分析时,更加便捷的获得人群的特征信息,从而更好的进行定量的分析。
业务画像分析流程:
1、默认情况下平台有业务的所有标签在MaxCompute中存储,同时也会存储一份Bitmap的标签索引数据,再标签数据更新时构建。
2、业务可以使用标签和其他用户相关的数据圈选人群,人群圈选完成后,也会对其构建一份Bitmap索引数据。
3、圈选完人群后,就会进行画像分析,如果标签和人群都有Bitmap索引数据,就会通过Bitmap进行分析
图片
技术平台早期画像分析主要依赖于MaxCompute执行SQL,但这种方式耗时较长,对于需要实时洞察分析的业务场景,分析需要更加快速看到结果,高延迟无法满足业务需求。之前尝试通过将数据导入Hologres进行加速,然而由于数据量庞大,Hologres的执行耗时仍然超过3分钟。
在前期,根据业务需求在技术上做了一些调研。从技术方案角度看,一些可以实现的画像分析的方案和其缺点:
图片
而Hologres原生支持RoaringBitmap数据结构,特别适合大数据量级下的交并差运算,并且在画像分析的场景天然适合,因此我们最后选择了RoaringBitmap方案。虽然RoaringBitmap会带来额外的处理和优化步骤、索引构建过程,这可能会带来一定的初期成本上升。然而,在既定的场景中,数据更新不是那么频繁,数据量级也在可控范围内,因此这一成本上升在可接受范围。而且使用RoaringBitmap带来的效率提升非常明显,最终还是选择使用这一方案进行标签和人群加速。
八 Bitmap的应用--美团DorisDoris是美团数据加工处理的产品,其在整个数仓的位置如下图所示
图片
在24年约Q3前后,从位运算、内存拷贝、接口、并发等四类场景对Doris中使用的Bitmap进行优化,如:
图片
图片
图片
图片
九 Bitmap其他应用场景数据库索引:Bitmap索引可以用于数据库查询,通过位运算快速判断记录是否满足查询条件缓存系统:使用Bitmap可以标记缓存中的对象,从而快速判断对象是否存在于缓存中网络流量监控:通过Bitmap标记网络流量中的数据包,可以快速检测异常流量数据压缩:使用Bitmap标记数据中的重复部分,可以减少存储空间的使用搜索引擎:使用Bitmap标记搜索结果中的关键词,可以快速过滤掉不相关的结果推荐系统:使用Bitmap标记用户或物品的特征,可以快速找到相似的用户或物品社交网络分析:使用Bitmap标记用户的行为或兴趣特征,可以快速找到具有相似兴趣的用户群体事件检测:使用Bitmap标记事件的相关特征,可以快速判断是否存在特定的事件数据清洗:使用Bitmap标记重复的数据记录,可以快速识别和处理重复的数据记录集合运算:在多个集合运算中,例如并集、交集、差集等,可以使用Bitmap来加速计算过程。通过将每个集合映射到一个Bitmap上,可以快速判断元素是否属于某个集合。哈希表冲突解决:在哈希表中,当两个不同的键哈希到同一个槽位时,可以使用Bitmap来标记这个槽位上的键值对,从而快速判断该槽位上是否存在冲突的键值对。位图排序:在处理大量数据时,可以使用位图排序算法来对数据进行排序。通过将数据元素映射到一个Bitmap上,然后根据Bitmap的状态对元素进行排序,可以实现高效的数据排序。范围查询:在数据库中执行范围查询时,可以使用Bitmap来加速查询过程。通过将查询条件映射到一个Bitmap上,可以快速判断满足条件的记录是否存在于数据库中。加密算法应用:在加密算法中,例如分组加密算法,可以使用Bitmap来标记每个分组中的元素,从而加速加密和解密过程。内存管理优化:在内存管理中,可以使用Bitmap来标记已分配和未分配的内存块。通过快速判断某个内存块是否已分配,可以优化内存分配和释放的过程。图像处理:在图像处理中,可以使用Bitmap来表示像素的颜色信息。通过将每个像素的颜色信息映射到一个Bitmap上,可以实现高效的图像处理操作。自然语言处理:在自然语言处理中,可以使用Bitmap来表示文本中的单词或短语。通过将每个单词或短语映射到一个Bitmap上,可以实现高效的文本分析和处理操作。机器学习应用:在机器学习中,可以使用Bitmap来表示特征向量中的每个特征。通过将每个特征映射到一个Bitmap上,可以加速特征向量的存储和计算过程。分布式系统应用:在分布式系统中,可以使用Bitmap来表示每个节点的状态信息。通过将每个节点的状态信息映射到一个Bitmap上,可以实现高效的节点状态管理和监控操作。十 Bitmap经典面试题解析题目1:什么是Bitmap?
Bitmap是一种数据结构,它使用二进制位来表示数据,可以高效地处理大量数据。
题目2:Bitmap有什么优点?
Bitmap的优点包括:
节省内存空间:使用二进制位表示数据,可以有效地减少内存占用。快速操作:通过位运算,可以快速地进行数据的查找、删除和更新等操作。适用于海量数据处理:可以处理大量的数据,并且处理效率较高。题目3:如何实现一个Bitmap?
实现一个Bitmap需要使用一个数组来存储二进制位,每个位表示一个数据元素是否出现。可以使用位运算来设置、清除和检查位的状态。
题目4:如何使用Bitmap进行数据的查找?
使用Bitmap进行数据的查找时,首先需要将数据元素的数值转换为对应的位索引,然后检查该位的状态。如果该位为1,则表示该数据元素出现;如果该位为0,则表示该数据元素未出现。
题目5:如何使用Bitmap进行数据的计数?
使用Bitmap进行数据的计数时,需要遍历所有的位,统计为1的位的数量即可。
题目6:如何使用Bitmap进行数据的删除?
使用Bitmap进行数据的删除时,需要将该数据元素对应的位设置为0,表示该数据元素不再出现。
题目7:如何优化Bitmap的性能?
使用缓存:将经常访问的位缓存起来,减少磁盘访问次数。使用压缩技术:对Bitmap数据进行压缩,减少内存占用和磁盘存储空间。使用多线程:使用多线程并行处理数据,提高处理效率。题目8:Bitmap适用于哪些场景?
数据库索引:可以使用Bitmap来快速判断某个数据元素是否存在。缓存系统:可以使用Bitmap来快速判断某个数据元素是否在缓存中。搜索引擎:可以使用Bitmap来快速过滤掉不需要的数据元素。数据压缩:可以使用Bitmap来快速判断某个数据元素是否需要被压缩。题目9:如何理解Bitmap的位运算?
位运算是一种二进制运算,包括与、或、异或、非等操作。在Bitmap中,可以使用位运算来设置、清除和检查位的值。例如,将第i位设置为1可以使用“1<<i”来表示;将第i位清除可以使用“~(1<<i)”来表示;检查第i位的值可以使用“(value & (1<<i)) != 0”来判断。
题目10:如何理解Bitmap的存储结构?
Bitmap的存储结构通常是一个数组,每个元素是一个二进制位。可以使用无符号整数类型来存储这个数组,也可以使用位向量或者位集等特殊的数据结构来存储这个数组。具体的存储结构取决于具体的应用场景和需求。
题目11:如何理解Bitmap的动态扩展?
当需要添加新的数据元素时,可能需要动态扩展Bitmap的大小。这可以通过创建一个新的更大的数组,并将原来的数据复制到新的数组中来实现。具体的扩展方式取决于具体的应用场景和需求。
题目12:如何理解Bitmap的内存优化?
在处理海量数据时,需要尽可能地节省内存空间。可以使用压缩技术来减少Bitmap所占用的内存空间。此外,还可以通过复用已经计算出来的结果来减少计算量,进一步提高效率。例如,可以将已经计算出来的结果缓存起来,避免重复计算。
题目13:如何理解Bitmap的并发操作?
在多线程环境下,需要对Bitmap进行并发操作。这需要使用线程安全的并发数据结构,例如ConcurrentHashMap或者AtomicInteger等。同时,还需要对并发操作进行合理的同步和调度,以避免数据不一致和竞态条件等问题。
题目14:如何理解Bitmap的位反转问题?
在Bitmap中,如果某个位被错误地设置或者清除,可能会导致位反转问题。这通常是由于位运算的错误或者硬件故障等原因引起的。为了避免位反转问题,可以使用校验和等技术来检测和修复错误。
题目15:如何理解Bitmap的索引问题?
在Bitmap中,每个位都对应一个数据元素。但是,如果需要查找某个具体的数据元素,需要遍历所有的位,这可能会非常耗时。为了解决这个问题,可以使用索引技术来快速定位到需要查找的数据元素。例如,可以使用哈希表或者B树等数据结构来建立索引。
题目16:如何理解Bitmap的动态扩容问题?
当Bitmap的大小不足以容纳新的数据元素时,需要进行动态扩容。这需要重新分配内存空间,并将原来的数据元素复制到新的数组中。这个过程可能会非常耗时,并且可能会影响程序的性能。为了解决这个问题,可以使用预分配技术来预先分配足够的内存空间,避免频繁的动态扩容操作。
题目17:如何理解Bitmap的位压缩问题?
在处理海量数据时,为了节省内存空间,需要对Bitmap进行位压缩。但是,压缩和解压缩的过程可能会非常耗时,并且可能会影响程序的性能。为了解决这个问题,可以使用高效的压缩和解压缩算法,例如LZ77或者Huffman编码等。
题目18:如何理解Bitmap的删除操作?
在Bitmap中,删除一个数据元素通常需要将该数据元素对应的位设置为0。但是,如果该数据元素对应的位已经被其他数据元素共享,那么删除该数据元素可能会影响其他数据元素的表示。为了解决这个问题,可以使用位运算中的异或操作来删除一个数据元素,而不会影响其他数据元素的表示。
题目19:如何理解Bitmap的位运算效率问题?
位运算是一种非常高效的运算方式,但是在进行复杂的位运算时,也可能会遇到效率问题。为了提高位运算的效率,可以使用一些优化技巧,例如使用缓存、并行计算、硬件加速等。同时,也可以使用一些高效的位运算库或者工具来提高效率。
题目20:如何理解Bitmap的适用场景和局限性?
Bitmap是一种非常高效的数据结构,但是也有一些局限性。例如,它不适合处理包含大量重复元素的数据集,因为这会导致大量的位被占用。此外,Bitmap也不适合处理需要频繁更新和查找的数据集,因为这可能会导致大量的磁盘I/O操作。因此,在使用Bitmap时需要考虑到它的适用场景和局限性。
十一 Bitmap算法题解析问题1:给定一个长度为n的整数数组,其中可能存在重复元素,要求使用Bitmap算法找出数组中只出现一次的元素。解答:首先,遍历数组并使用Bitmap记录每个元素出现的次数。然后,再次遍历Bitmap,找到只出现一次的元素对应的位,即为所求。
问题2:有两个非常大的整数集合A和B,要求使用Bitmap算法求出它们的交集。解答:首先,将集合A和B分别转换为Bitmap。然后,对两个Bitmap进行按位与运算,得到的结果即为它们的交集。
问题3:给定一个长度为n的整数数组和一个目标整数target,要求使用Bitmap算法判断数组中是否存在两个数的和等于target。解答:首先,遍历数组并使用Bitmap记录每个元素的出现情况。然后,对于每个元素num,检查target - num是否在Bitmap中存在,如果存在则说明存在两个数的和等于target。
问题4:给定一个长度为n的整数数组,要求使用Bitmap算法找出数组中出现次数最多的k个元素。解答:首先,遍历数组并使用Bitmap记录每个元素出现的次数。然后,对Bitmap进行排序,找到出现次数最多的k个元素对应的位即可。
问题5:给定一个长度为n的整数数组和一个整数k,要求使用Bitmap算法找出数组中是否存在长度为k的连续子数组的和等于某个给定值。解答:首先,使用滑动窗口遍历数组并计算窗口内元素的和。然后,使用Bitmap记录每个和的出现情况。如果某个和的值在Bitmap中出现过,则说明存在长度为k的连续子数组的和等于该值。
问题6:给定两个非常大的整数集合A和B,要求使用Bitmap算法求出它们的并集。解答:首先,将集合A和B分别转换为Bitmap。然后,对两个Bitmap进行按位或运算,得到的结果即为它们的并集。
问题7:给定一个长度为n的整数数组和一个整数k,要求使用Bitmap算法找出数组中是否存在两个数的差的绝对值等于k。解答:首先,遍历数组并使用Bitmap记录每个元素的出现情况。然后,对于每个元素num,检查num + k和num - k是否在Bitmap中存在,如果存在则说明存在两个数的差的绝对值等于k。
问题8:给定一个长度为n的整数数组和一个整数m,要求使用Bitmap算法判断数组中是否存在一个子集的和等于m。解答:该问题可以使用动态规划和Bitmap结合解决。首先,创建一个长度为m+1的Bitmap,并初始化第0位为1。然后,遍历数组并使用动态规划的思想更新Bitmap的每个位。最后,检查Bitmap的第m位是否为1,如果是则说明存在一个子集的和等于m。
问题9:给定一个长度为n的整数数组和一个整数target,要求使用Bitmap算法找出数组中是否存在三个数的和等于target。解答:首先,遍历数组并使用Bitmap记录每两个数的和的出现情况。然后,对于每个元素num,检查target - num是否在Bitmap中存在,如果存在则说明存在三个数的和等于target。
问题10:给定一个长度为n的整数数组和一个整数k,要求使用Bitmap算法找出数组中是否存在长度为k的子数组的异或和等于0。解答:该问题可以使用前缀异或和和Bitmap结合解决。首先,计算数组的前缀异或和并存储在另一个数组中。然后,遍历前缀异或和数组并使用Bitmap记录每个值的出现情况。最后,检查是否存在两个前缀异或和的差等于0且它们之间的距离为k-1,如果存在则说明存在长度为k的子数组的异或和等于0。
十二 参考资料[1] BitMap 的基本原理和实现:https://blog.csdn.net/u010412301/article/details/89377162
[2] Bitmap的原理和应用:https://www.cnblogs.com/felixzh/p/15746669.html
[3] Bitmap、RoaringBitmap原理分析:https://baijiahao.baidu.com/s?id=1761206677884050539&wfr=spider&for=pc[4] BloomFilter概念和原理以及业务中的应用场景 :https://blog.csdn.net/weixin_47533244/article/details/129317127
[5] Redis之bitmap类型解读:https://blog.csdn.net/m0_62436868/article/details/132424914
[6] Hologres RoaringBitmap实践:千亿级画像数据秒级分析:https://it.sohu.com/a/721472386_120583536
[7] 美团 Doris Bitmap 精确去重优化实践:https://mp.weixin.qq.com/s/XNWVb4CMPCAZfEBWRPROyQ炒股配资门户
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。天盈配资提示:文章来自网络,不代表本站观点。