MongoDB中数十亿小文档的快速搜索策略

MongoDB中数十亿小文档的快速搜索策略,mongodb,search,scalability,pymongo,database-performance,Mongodb,Search,Scalability,Pymongo,Database Performance,我需要存储数十亿个小数据结构(每个大约200字节)。到目前为止,将每个元素存储为单独的文档效果良好,Mongo每秒提供大约10000个结果。我使用一个20字节的散列作为每个文档的_id,在_id字段上使用一个索引。在测试中,这适用于包含5000000个文档的数据集 在操作中,我们将每秒发出约10000个请求,每秒更新现有文档1000次,插入新文档的次数可能在每秒100次或更少 当我们不能在RAM中存储整个索引时,我们如何管理更大的数据集?如果我们将几个元素组合到每个文档中,MongoDB的性能会

我需要存储数十亿个小数据结构(每个大约200字节)。到目前为止,将每个元素存储为单独的文档效果良好,Mongo每秒提供大约10000个结果。我使用一个20字节的散列作为每个文档的_id,在_id字段上使用一个索引。在测试中,这适用于包含5000000个文档的数据集

在操作中,我们将每秒发出约10000个请求,每秒更新现有文档1000次,插入新文档的次数可能在每秒100次或更少

当我们不能在RAM中存储整个索引时,我们如何管理更大的数据集?如果我们将几个元素组合到每个文档中,MongoDB的性能会更好吗?这样可以更快地搜索索引,但在每个查询中返回更多数据

与其他问题不同的是,我不仅对我们可以将多少数据塞进Mongo感兴趣。它可以清楚地管理我们正在查看的数据量。我关心的是,在内存受限的情况下,如何最大限度地提高大型集合上的
查找
操作的速度

我们的搜索将趋向于集群化;大约50000个元素将满足大约50%的查询,但剩余的50%将随机分布在所有数据中。我们是否可以通过将这50%的数据转移到它们自己的集合中,以使最常用数据的索引始终保持在ram中,从而获得性能提升


将_id字段的大小从20字节减少到8字节是否会对MnogoDB的索引速度产生重大影响?

我想到了一些策略:

1) 对“热门”文档使用不同的集合/数据库

如果您知道哪些文档在热集中,那么,是的,将它们移动到单独的集合中会有所帮助。这将确保热文档共同驻留在相同的扩展数据块/页面上。它还将使这些文档的索引更有可能完全存储在内存中。这是因为它更小,而且(完全?)使用更频繁

如果热文档与其他文档随机混合,则在加载文档时,您可能不得不在B树索引的更多叶元素中出错,因为另一个文档最近加载或访问索引块的概率很小

2) 缩短索引值

索引值越短,适合单个B树块的值就越多。(注意:索引中不包括键。)单个存储桶中的条目越多,意味着存储桶越少,索引所需的总内存越少。这意味着块留在内存中的概率更高/寿命更长。在您的示例中,减少20->8个字符比节省50%要好。如果您可以将这8个字节转换为long,那么就可以节省一点,因为long没有长度前缀(4个字节)和尾部null(总共5个字节)

3) 缩短密钥名称

字段名称越短,每个文档占用的空间越小。 这有一个不幸的副作用,即降低可读性

4) 碎片

这确实是在整个语料库的读取耗尽内存和最终磁盘带宽时保持性能的唯一方法。如果你做切分,你仍然想切分“热门”收藏

(五)

由于“非热”读取是从磁盘加载一个随机文档,所以我们实际上只想将该文档和尽可能少的文档读取/出错到内存中。一旦用户从文件的一部分读取数据,大多数系统都会尝试提前读取一大块数据。这与我们想要的恰恰相反

如果您看到您的系统故障很多,但mongod进程的驻留内存不接近系统可用内存,那么您可能会看到操作系统读取无用数据的效果

6) 尝试对键使用单调递增的值

这将触发一个优化(针对基于ObjectId的索引),当索引块拆分时,它将以90/10而不是50/50进行拆分。结果是,索引中的大多数块将接近容量,您将需要更少的块

如果您只知道“热门”50000个文档,那么按索引顺序将它们添加到单独的集合中也会触发此优化


Rob。

因为听起来您的文档比RAM多得多,所以我会尽可能地缩小文档,以增加RAM中可以容纳的数据量。例如,确保字段名仅为一个或两个字符。你打算分片吗?将数据移动到同一服务器上的不同集合不会改变RAM的使用情况,因为它是由操作系统管理的。随着数据的增长,我们将进行切分。将最常用的记录放在不同的集合中只是一个想法,以便将这个较小集合的索引保留在RAM中,并尽量避免将其交换出去。我认为这可能是幼稚的,但我不确定为什么。索引的内存不是独立于工作集所需的内存来管理的。这一切都由操作系统管理。如果索引经常使用(比数据更频繁),它应该保留在内存中。坦率地说,如果没有更多细节,很难判断,但在我看来,优化MongoDB的大N查询性能并不是这里要解决的问题。您关于将较少使用的数据移动到单独的集合中的问题是朝着这个方向迈出的一步,但我会更进一步:将完整的数据集保存在mongo中,并将这些50k大容量记录的独立副本放在离处理请求更近的地方。但在这一点上,我们进入了您的一致性要求是什么。。。又名“有趣的领域”。