文章插图
复杂度分析
通过上面的例子我们可以看到,在时间复杂度方面查找候选规则集时,进行一轮 || 运算,一轮 & 运算;在查找最优规则时进行一轮 & 运算,所以整体复杂度是 3n≈n 。
在空间复杂度方面,相比原来的行式存储,倒排索引的存储方式,每列都需要存储行 ID,相当于多了 *(n-1)Posting List 存储空间,当然这是粗略计算,因为实际上行 ID 的存储最终转换为位图存储,在空间上有非常大的压缩空间 。
工程问题 - 压缩位图
如果倒排索引位图非常稀疏,系统会存在非常大的空间浪费 。我们举一个极端 case,若千万规则库中命中的行 ID 是第 1000 万位,按照传统方式 BitSet 进行存储,需要消耗 1.2MB 空间,在内存中占用存在严重浪费,有没有压缩优化方案,在 RoaringBitMap 压缩位图方案中我们找到,相同场景在压缩位图方式下仅占 144bytes;即使在 1000 万的位图空间,我们随机存储 1 万个值,两者比也是在 31K vs 2MB,近 100 倍的差距,总的来说 RoaringBitMap 压缩率非常大 。
RoaringBitMap 本质上是将大块的 bitmap 拆分成各个小块,其中每个小块在需要存储数据的时候才会存在,所以当进行交集或并集运算的时候,RoaringBitMap 只需要去计算存在的块而不需要像 bitmap 那样对整个大块进行计算,既做到了压缩的存储又做到计算性能的提升 。
以下图 821697800 为例,对应的 16 进制数为 30FA1D08, 其中高 16 位为 30FA,低 16 位为 1D08 。先用二分查找从一级索引(即 Container Array)中找到数值为 30FA 的容器,该容器是一个 Bitmap 容器,然后在该容器查找低 16 位的数值 1D08,即十进制下 7432,在 Bitmap 中找到相应的位置,将其置为 1 即可 。
文章插图
适用场景分析
回顾上面的设计方案我们可以看到,这种方式仅适用于 PostingList 简单如行 ID 的形式,如果是复杂对象就不适合用位图来存储 。另外仅适用于等值查询,不适用于 like、in 的范围查询,为什么有这种局限性?因为这种方式依赖于搜索条件的空间,在方案中我们将值的条件作为搜索的 Key,值的条件空间希望尽可能是一个有限的、方便穷举的、小的空间 。而范围查询导致这个空间变成难以穷举、近乎无限扩张的、所以不适用 。
其他优化方式
除了使用位运算的方式对倒排索引加速,考虑到 Posting List 的有序性,还有其他的方式比如使用跳表、Hash 表等方式,以 ES 中采用的跳表为例,进行 & 运算实际就是在查找两个有序 Posting List 公共部分,以相互二分查找的形式,将时间复杂度控制在 log (n) 的级别 。
具体参见《工业界如何利用跳表、哈希表、位图进行倒排索引加速?》:https://time.geekbang.org/column/article/221292?utm_source=related_read&utm_medium=article&utm_term=related_read
文章插图
推荐阅读
- 美国演员工会|亮剑:李云龙的吃席,对比场景,旧版输在了哪里?
- 官宣|?性感女星恋上50岁离异胖老头!男方直播捞百万,对女方妈妈上下其手母女通吃?
- 梁左|被英达坑骗梁左背负百万债务,去世落在女儿身上最后延续父亲事业
- 演唱会|《大侦探8》来了!新春演唱会华丽阵容及场景曝光,期待首发案件
- 官宣|?性感女星恋上50岁离异胖老头!男方直播捞百万,母女通吃!
- 郑爽|3位“网络名人”力挺郑爽,坐拥百万粉丝,曾为吴某凡霍尊说话
- 如何一年赚100万(干什么最赚钱一年赚百万)
- 肖战|YSL一夜退货超三百万,肖战成了无辜背锅侠?!
- 陈萌|陈萌自曝体重仅90斤,疑戴百万辣绿翡翠手镯,网友:当心不孕不育
- 传输层协议有哪些(消息队列的使用场景)