为MongoDB建模应用程序数据时,应考虑影响MongoDB性能的各种操作因素。例如,不同的数据模型可以允许更有效的查询,增加插入和更新操作的吞吐量或更有效地将活动分配给分片群集。
开发数据模型时,请结合以下注意事项来分析应用程序的所有 读写操作。
在MongoDB中,写操作是对单个文件的能级,即使操作修改多个嵌入式文档
内的单个文件。当单个写入操作修改多个文档(例如db.collection.updateMany()
)时,对每个文档的修改都是原子的,但整个操作不是原子的。
对于在相关数据之间存储引用的数据模型,应用程序必须发出单独的读取和写入操作以检索和修改这些相关数据。
对于需要对多个文档(在单个或多个集合中)进行读写原子性的情况,MongoDB支持多文档事务:
有关MongoDB中事务的详细信息,请参阅 事务页面。
重要
在大多数情况下,与单文档写入相比,多文档事务产生的性能成本更高,并且多文档事务的可用性不应代替有效的架构设计。在许多情况下, 非规范化数据模型(嵌入式文档和数组)对于您的数据和用例将继续是最佳的。也就是说,在许多情况下,对数据进行适当的建模将最大程度地减少对多文档交易的需求。
有关其他事务使用方面的注意事项(例如运行时限制和oplog大小限制),另请参见 生产注意事项。
MongoDB使用分片提供水平扩展。这些集群支持具有大数据集和高吞吐量操作的部署。分片允许用户在数据库中对集合进行分区,以
在多个实例或分
片中分布集合的文档。mongod
为了在分片集合中分发数据和应用程序流量,MongoDB使用分片密钥。选择适当的分片 键会对性能产生重大影响,并且可以启用或阻止查询隔离以及增加的写容量。务必仔细考虑用作分片键的一个或多个字段,这一点很重要。
使用索引可以提高常见查询的性能。在查询中经常出现的字段以及返回排序结果的所有操作上建立索引。MongoDB在_id
字段上自动创建唯一索引
。
创建索引时,请考虑以下索引行为:
在某些情况下,您可能选择将相关信息存储在多个集合中,而不是存储在单个集合中。
考虑一个样本收集logs
,该样本存储用于各种环境和应用程序的日志文档。该logs
集合包含以下格式的文件:
如果文档总数很少,则可以按类型将文档分组到集合中。对于日志,请考虑维护不同的日志集合,例如logs_dev
和logs_debug
。该logs_dev
集合将仅包含与开发环境有关的文档。
通常,具有大量集合不会造成明显的性能损失,并且会导致非常好的性能。不同的集合对于高通量批处理非常重要。
当使用具有大量集合的模型时,请考虑以下行为:
_id
至少需要8 kB的数据空间。<database>.ns
)存储该数据库的所有元数据,并且每个索引和集合在名称空间文件中都有其自己的条目。MongoDB的地方。limits on the size of namespace files
如果您有一个包含大量小文档的集合,则出于性能原因,应考虑嵌入。如果您可以按某种逻辑关系将这些小文档分组,并且经常通过此分组来检索文档,则可以考虑将这些小文档“汇总”到包含嵌入式文档数组的较大文档中。
将这些小文档“汇总”为逻辑分组意味着,检索一组文档的查询涉及顺序读取和较少的随机磁盘访问。此外,“汇总”文档并将公共字段移动到较大的文档也有利于这些字段上的索引。会有共同领域的较少副本和也就会相应减少指标相关联的密钥条目。有关索引的更多信息,请参见 索引。
但是,如果您通常只需要检索组中文档的一个子集,则“汇总”文档可能无法提供更好的性能。此外,如果小的单独文档代表数据的自然模型,则应维护该模型。
每个MongoDB文档都包含一定量的开销。这种开销通常并不重要,但是如果所有文档都只有几个字节,那么这将变得很重要,如果您集合中的文档只有一个或两个字段,则可能会发生这种情况。
请考虑以下建议和策略,以优化这些集合的存储利用率:
_id
显式使用该字段。
MongoDB客户端会自动_id
向每个文档添加一个字段,并为该
字段生成一个唯一的12字节的ObjectId_id
。此外,MongoDB始终为该_id
字段编制索引。对于较小的文档,这可能会占用大量空间。
为了优化存储使用,_id
在将文档插入集合中时,用户可以为该字段显式指定一个值。此策略允许应用程序在_id
字段中存储一个值,该值本来会在文档的另一部分中占用空间。
您可以在_id
字段中存储任何值,但是由于此值用作集合中文档的主键,因此它必须唯一地标识它们。如果该字段的值不是唯一的,则它不能用作主键,因为在集合中会发生冲突。
使用较短的字段名称。
注意
缩短字段名称会降低表达能力,并且对于较大的文档以及文档开销不太重要的情况,不会带来很大的好处。较短的字段名称不会减少索引的大小,因为索引具有预定义的结构。
通常,没有必要使用短字段名。
MongoDB在每个文档中存储所有字段名称。对于大多数文档,这只占文档使用空间的一小部分;但是,对于小型文档,字段名称可能会按比例表示大量的空间。考虑类似于以下内容的小文件的集合:
如果缩短名为外地last_name
来lname
并命名为外地best_score
来score
,如下所示,你可以保存每个文档9个字节。
嵌入文件。
在某些情况下,您可能希望将文档嵌入其他文档中,并节省每个文档的开销。请参阅 集合包含大量的小文档。
数据建模决策应考虑数据生命周期管理。
在生存时间或TTL功能集合在一段时间后过期的文件。如果您的应用程序需要一些数据在有限的时间内保留在数据库中,请考虑使用TTL功能。
此外,如果您的应用程序仅使用最近插入的文档,请考虑上限集合。皑皑的藏品提供先入先出(FIFO)的管理文件插入,并有效地支持业务的是插入和读取基于插入顺序文件。