我正在观看Adrien Grand的talk on Lucene's index architecture,他提出的一点是,Lucene使用排序数组来表示其倒排索引的字典部分。使用排序数组而不是散列表(“经典”倒排索引数据结构)背后的原因是什么?
哈希表提供了O(1)插入和访问,对我来说似乎对快速处理查询和合并索引段有很大帮助。另一方面,排序的数组只能提供O(logN)访问和(gasp)O(N)插入,尽管合并2个排序的数组与合并2个哈希表的复杂性相同。
我能想到的散列表的唯一缺点是更大的内存占用(这可能确实是一个问题)和更少的缓存友好性(尽管像查询排序数组这样的操作需要二进制搜索,这就像缓存不友好一样)。
那是怎么回事? Lucene开发人员必须有一个很好的理由使用数组。这与可扩展性有关吗?磁盘读取速度?还有其他什么呢?
答案 0 :(得分:2)
好吧,我会在这里推测(应该是评论 - 但它会太长)。
HashMap
通常是快速查找结构,搜索时间O(1)
- 意味着它是常量。但这是平均情况;因为(至少在Java中)HashMap
使用TreeNodes
- 该桶内的搜索为O(logn)
。即使我们认为他们的搜索复杂度为O(1)
,但这并不意味着它的时间相同。它只是意味着每个独立的数据结构都是不变的。
记忆确实 - 我会举一个例子here。简而言之,存储15_000_000
条目需要稍微超过1GB
的RAM;排序的数组可能更紧凑,特别是因为它们可以保存基元而不是对象。
将条目放入HashMap
(通常)需要所有重新散列的密钥,这可能会对性能造成重大影响,因为它们都必须移动到不同的位置潜在地
这里可能还有一点 - 在范围内搜索,可能需要一些TreeMap
,这里的数组更适合。我正在考虑对索引进行分区(可能是他们在内部进行)。
我和你有同样的想法 - 数组通常是连续的内存,可能更容易被CPU预取。
最后一点:把我放到他们的鞋子里,我先从HashMap
开始......我相信他们的决定有令人信服的理由。我想知道他们是否有实际的测试来证明这个选择。