[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fA8pH1wcDlyIhEzcxaCzzEngkGlrWuGUlOlaHrKpZIPk":3},{"item":4,"related":44},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":36,"sourceUrl":37,"status":38,"seoTitle":7,"seoDescription":9,"canonicalUrl":35,"isFeatured":39,"sno":40,"sortOrder":41,"publishedAt":42,"updatedAt":43,"createdAt":43},"09f0ce1a-a9e1-4797-96b2-4c4da31b3534","article","Roaring Bitmap：如何把大量整数集合压缩起来，还能快速求交集？","roaring-bitmap-compressed-integer-sets","Roaring Bitmap 按整数高位分块，并根据局部密度选择数组或位图容器，在压缩表示上执行精确集合运算。本文解释自适应容器的工作方式，并与可能误报的 Bloom Filter 区分。","如果要表示一个整数集合，例如“哪些用户参加过活动”“哪些文档包含某个词”，位图是一种简单高效的办法：用第 n 位表示整数 n 是否存在。可当整数范围特别大、实际成员却很稀疏时，直接分配一整张位图会浪费空间。Roaring Bitmap（Roaring 位图）通过把整数按高位分块，并为每块选择合适的容器，兼顾压缩与快速集合运算。\n\n一个常见设计会把 32 位整数拆成高 16 位和低 16 位。高位用来定位块，低位值则存放在该块的容器里。若某个块只有少数成员，就用紧凑的有序数组；成员密度升高时，可切换到固定大小的位图容器。这样稀疏区域不必承担密集位图的空间成本，而密集区域还能利用机器字并行执行按位运算。\n\n这类结构的优势不只是压缩。对两个 Roaring 集合做交集、并集、差集时，可以按块匹配容器，依据容器类型选用合适算法。例如数组与数组可以合并比较，位图与位图可以做机器字级 AND，混合类型也可使用专门路径。许多分析查询因此能直接在压缩后的结构上运行，避免先展开成完整大位图。\n\n容器之间可以采用不同表示，是 Roaring 与单一编码方案的重要区别。它仍是精确集合：如果某整数在集合里，查询就返回存在；若不在，就返回不存在。Bloom Filter 则是概率型成员测试，空间更省，但可能出现“误报存在”。两者解决的问题不同：Roaring 适合需要精确成员关系与集合运算，Bloom Filter 适合用很小空间先排除大多数不存在的元素。\n\n不过，“压缩”不意味着任何数据上都更小。若集合分布不理想，元数据、容器切换和序列化格式都会影响实际占用；频繁随机更新也可能带来维护开销。评估时要看整数范围、密度分布、读写比例以及需要执行的运算，而不是只比较理论上的每个元素几位。\n\n可以把 Roaring 想成一座按街区管理的档案馆：先按邮区找到一个小柜，再根据柜子里材料多寡，使用薄薄的名册或完整索引卡墙。查询和合并都能在柜子内部处理，不必把整座城市的空地址全部列出来。它的核心价值是为整数集合提供一种自适应、可精确计算的表示方式，常见于搜索引擎、数据库、分析系统和日志处理。\n\n来源：[Chambi 等：Better bitmap performance with Roaring bitmaps](https:\u002F\u002Farxiv.org\u002Fabs\u002F1709.07821)","\u002Fuploads\u002F2026-10-13\u002F6c8cbd02-1f3a-4b4c-8e59-83567ff42d51.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"Roaring Bitmap Research Paper","https:\u002F\u002Farxiv.org\u002Fabs\u002F1709.07821","published",false,51,0,"2026-10-13T00:00:00.000Z","2026-10-13T02:14:10.351Z",[45,54,62],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":52,"createdAt":53},"5e0c84da-6011-41e8-b1f7-726c8bf0b30a","RCU：读多写少的系统，为什么敢让读者几乎不加锁？","rcu-read-copy-update-explained","RCU 把共享数据的更新与旧版本回收拆开，让读者以极低成本读取，同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。","\u002Fuploads\u002F2026-09-26\u002F3398ce37-ca4f-4cc3-84b3-fe931d2f055d.jpg",41,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:40.784Z",{"id":55,"type":6,"title":56,"slug":57,"summary":58,"coverUrl":59,"authorName":14,"sno":60,"publishedAt":42,"createdAt":61},"0bc79f1c-f305-4d64-a9f8-589d1d6da0b3","EEVDF：Linux 如何判断哪个任务“最该先用 CPU”？","eevdf-linux-fair-cpu-scheduling","EEVDF 是 Linux 调度器的一种公平调度思路：先判断任务是否获得了应有份额，再按虚拟截止时间安排运行机会。本文用共享厨房的比喻，解释它如何兼顾长期公平与短期响应，并澄清它并非硬实时保证。","\u002Fuploads\u002F2026-10-13\u002Fdc59d374-8c78-41ba-bdfe-a6f0e62ab246.jpg",43,"2026-10-13T02:13:28.103Z",{"id":63,"type":6,"title":64,"slug":65,"summary":66,"coverUrl":67,"authorName":14,"sno":68,"publishedAt":52,"createdAt":69},"23b5596a-29ab-4ff8-8237-1fd34d8e0bd1","Seqlock：读者不加锁，为什么还能读到一份一致的数据？","seqlock-sequence-counter-explained","Seqlock 让读者先后读取序列号并在变化时重试，以校验快照是否被写者打断，适合读多写少且字段可安全复制的数据。","\u002Fuploads\u002F2026-09-26\u002Fe6a9caee-7551-469f-9b16-d27fcc97f034.jpg",44,"2026-09-26T16:25:51.305Z"]