让我根据我的全球知识和经验给你一些提示:
使用较短的字段名称
MongoDB 为每个文档存储相同的密钥。这种重复会导致磁盘空间增加。对于像您这样的非常大的数据库来说,这可能会产生一些性能问题。
Pros:
- 文档大小较小,因此磁盘空间较小
- RAM 中可容纳更多文档(更多缓存)
- 在某些情况下 do 索引的大小会更小
Cons:
优化索引大小
索引大小越小,它就越适合 RAM,并且索引丢失的情况也就越少。例如,考虑 git 提交的 SHA1 哈希值。 git 提交很多时候由前 5-6 个字符表示。然后只需存储 5-6 个字符而不是所有哈希值。
了解填充因子
对于文档中发生的更新导致昂贵的文档移动。此文档移动导致删除旧文档并将其更新到新的空位置并更新索引,这是昂贵的。
我们需要确保文档在发生更新时不会移动。对于每个集合,都涉及一个填充因子,它告诉在文档插入期间,除了实际文档大小之外要分配多少额外空间。
您可以使用以下命令查看集合填充因子:
db.collection.stats().paddingFactor
手动添加填充
就您而言,您很肯定会从一个会增长的小文档开始。稍后更新文档将导致多个文档移动。因此最好为文档添加填充。不幸的是,没有简单的方法来添加填充。我们可以通过在插入时向某个键添加一些随机字节,然后在下一个更新查询中删除该键来实现。
最后,如果您确定某些键将来会出现在文档中,请为这些键预先分配一些默认值,以便进一步的更新不会导致文档大小的增长,从而导致文档移动。
您可以获得有关导致文档移动的查询的详细信息:
db.system.profile.find({ moved: { $exists : true } })
大量集合 VS 少量集合中的大量文档
架构取决于应用程序的需求。如果有一个巨大的集合,其中我们只查询最近N天的数据,那么我们可以选择单独的集合,并且可以安全地归档旧数据。这将确保 RAM 中的缓存正确完成。
创建的每个集合都会产生比创建集合的成本更高的成本。每个集合的最小大小为几 KB + 一个索引 (8 KB)。每个集合都有一个关联的命名空间,默认情况下我们有一些 24K 命名空间。例如,每个用户都有一个集合是一个糟糕的选择,因为它不可扩展。过了某个时刻,Mongo 将不允许我们创建新的索引集合。
一般来说,拥有许多集合不会造成明显的性能损失。例如,如果我们知道我们总是基于月份进行查询,那么我们可以选择每月一次收集。
数据非规范化
始终建议将查询或查询序列的所有相关数据保留在同一磁盘位置。您需要在不同的文档中复制信息。例如,在博客文章中,您需要将帖子的评论存储在帖子文档中。
Pros:
- 随着索引条目数量的减少,索引大小将非常小
- 查询将非常快,其中包括获取所有必要的详细信息
- 文档大小将与页面大小相当,这意味着当我们将此数据放入 RAM 中时,大多数时候我们不会将其他数据带入页面
- 文档移动将确保我们释放一个页面,而不是页面中可能不会在进一步插入中使用的一小部分
上限集合
上限集合的行为类似于循环缓冲区。它们是特殊类型的固定大小集合。这些集合可以接收非常高速的写入和顺序读取。由于大小固定,一旦分配的空间被填满,新文档就会通过删除旧文档来写入。但是,仅当更新的文档适合原始文档大小时才允许文档更新(使用填充以获得更大的灵活性)。