我有一个池集(池n的大小),所有集合都不适合RAM。我只能适应一小部分,比如将所有集合的1-5%放入RAM中。
问题是查询集Q我需要返回与Q相交的最大基数的前k个集。
k很小,有数百,而n是数亿。所有集合中的区域元素总数也达数亿。
我做了一些实验,将集合表示为布隆过滤器。由于集合大小变化很大,我必须使用非常大的bloomfilters,这是低效的(bloomfiltes占用原始数据集的5倍空间)。来自https://github.com/jaybaird/python-bloomfilter的自适应bloomfiters只产生3-5倍的数据集压缩,因此这仍然是不可行的。
答案 0 :(得分:4)
K-Minimum Values数据结构极其节省内存。与Bloom过滤器不同,它不提供成员资格测试,只提供集合理论操作和基数估计。
可能会为您工作,具体取决于您的设置的基数和容错能力。
答案 1 :(得分:2)
将所有集合保存在一个包含(setId, value)
形式的键的bloom过滤器中。这将必须能够处理所有集合的并集大小的集合,这使您无法将大型集合存储在大型的大型过滤器中。
其次,为了您的目的,您可能会接受非常大的错误率,这再次让布隆过滤器缩小。具有1%错误率的布隆过滤器需要每个元素9.58505837736744 ...位。具有10%错误率的布隆过滤器每个元素需要4.79252918868372位。但是如果你有一个10%的错误率,在400元素集上,你可以在纠正预期的误报后,在正确答案的3%范围内得到95%的答案。这可能是可以接受的,以使滤波器尺寸减少2倍。 (Q越大,相对误差越小。)
如果在这两种技术之间使用布隆过滤器仍然太大,那么您应该考虑在多台计算机上分发数据......
答案 2 :(得分:2)
实际上,我找到了解决方案。通过乘以hyperloglog和minhash给出的交集,并且可以使用LSH有效地存储minhashes。更多详情:http://infolab.stanford.edu/%7Eullman/mmds/ch3.pdf
答案 3 :(得分:1)
如果将查询集Q保留在内存中作为哈希表,则无需同时将所有其他集保留在内存中。您可以一个接一个地计算每个集合的交叉点基数。只需将一个集合加载到内存中,计算其与Q的交集的基数,最后再从内存中删除它。