MongoDB:存储和何时使用关系
Posted
技术标签:
【中文标题】MongoDB:存储和何时使用关系【英文标题】:MongoDB: storage & when to use relationships 【发布时间】:2011-07-07 11:34:11 【问题描述】:我是 MongoDB 新手,请多多包涵。
我有两个问题:
首先,采取以下措施:
// add a record
$obj = array( "title" => "Calvin and Hobbes", "author" => "Bill Watterson" );
MongoDB 是否将“标题”和“作者”存储为该集合中该对象的每个条目的文本?还是它会创建一个模式并将这些转换为字段编号(或根本不存储数据并仅存储数据)?
我的第二个问题是:什么时候应该使用“关系”?假设我有 100 个经销商,每个经销商包含(对象)1,000 个客户,每个客户有 10 个项目。这样就可以操纵一个巨大的整体对象。
在 SQL 世界中,这都是相关的“对象”。在 Document 世界中,我们尝试通过嵌入子对象来存储完整的对象。
但是,这可能很笨拙。对此的最佳做法是什么?有人可以指点我的指导方针吗?
谢谢。
【问题讨论】:
是的,title
和 author
以文本形式存储在数据库中。根据您使用的语言/驱动程序/包装器,这通常可以重新映射,以便该字段在数据库中为t
,但在从您的对象访问时为title
。从关系的角度来看,您通常会发现您必须针对“某事”进行优化。没有单一的“最佳方式”。
下次请将您的问题拆分为单独的 *** 问题。
【参考方案1】:
MongoDB 是否存储“标题”和 “作者”作为每个单曲的文本 此对象在此中的条目 收藏?
MongoDB 是无模式的 - 所以答案很明显:是的,因为没有模式这种东西
我的第二个问题是:什么时候应该 “关系”可以用吗?假设我有 100 个经销商,他们包含 (对象方面)每个 1,000 个客户,以及 每个客户有 10 个项目。那 构成一个巨大的整体对象 操纵。
请检查
http://www.mongodb.org/display/DOCS/Schema+Design
您的选择是嵌入文档、数据库引用或多个查询。
【讨论】:
不确定“答案很明显”是否适用 - 显然不是,否则 OP 不会问。这是与 SQL 世界不同的范式,诸如数据存储方式之类的常见问题解答将会出现并且是有保证的。【参考方案2】:MongoDB 是否为该集合中的每个条目命名?
是的,MongoDB 确实存储了每条记录的文本。实际上,如果磁盘空间是一个限制因素,这通常不是什么大问题,您可能需要考虑其他因素。
什么时候应该使用“关系”?
这更像是一门艺术而不是一门科学。 Mongo Documentation on Schemas 是一个很好的参考,但这里有一些事情需要考虑:
尽可能多地投入
文档数据库的乐趣在于它消除了许多连接。您的第一直觉应该是尽可能多地放在一个文档中。因为 MongoDB 文档具有结构,并且您可以在该结构中有效地查询,所以不需要像在 SQL 中那样立即规范化数据。特别是,除了其父文档之外无用的任何数据都应该是同一文档的一部分。
可以从多个地方引用到自己的集合中的分离数据。
这与其说是“存储空间”问题,不如说是“数据一致性”问题。如果许多记录将引用相同的数据,则更新单个记录并在其他地方保留对它的引用会更有效且更不容易出错。
文档大小注意事项
MongoDB 对单个文档施加了 4MB 的大小限制。在 GB 数据的世界中,这听起来很小,但它也是 3000 万条推文或 25 万条典型的 Stack Overflow 答案或 20 张闪烁的照片。另一方面,这比一个人可能希望在典型网页上一次呈现的信息要多得多。首先考虑什么会使您的查询更容易。在许多情况下,对文档大小的担忧将是过早的优化。
在您提供的示例中,我将创建 3 个单独的集合,因为我不需要了解其他 9 个项目来为项目创建列表。我将保持简单的查询。 (但请参阅底部的 Protip)
复杂的数据结构:
MongoDB 可以存储任意深度嵌套的数据结构,但不能有效地搜索它们。如果您的数据形成树、森林或图形,您实际上需要将每个节点及其边缘存储在单独的文档中。 (请注意,有专门为此类数据设计的数据存储,也应考虑)
数据一致性
MongoDB 在效率和一致性之间进行权衡。规则是对单个文档的更改始终是原子的,而对多个文档的更新不应该被认为是原子的。也没有办法“锁定”服务器上的记录(您可以使用例如“锁定”字段将其构建到客户端的逻辑中)。在设计架构时,请考虑如何保持数据的一致性。通常,您在文档中保存的越多越好。
专业提示
即使您确实使用了引用,在父文档中保留一些来自引用的数据通常也是一个好主意。通常,我会保留足够的信息来建立与父代中的后代的有意义的链接。
在您的示例中,这意味着将客户名称与 ObjectID 一起保存在经销商的文档中,这样我就可以按名称创建指向每个客户的链接,而无需单独查询。如果为客户端构建 URL 需要除文档 ID 之外的其他内容,我也会存储它。
这样的技巧可以减少 1+n 查询的情况。
【讨论】:
请注意,MongoDB 的最新版本现在高达 16MB。那是1.8.0版。因此,如果您开始一个新项目,16MB 将是您的“新”最大值。 我们被建议不要使文档过大,因为这可能会影响性能。这是个坏建议吗? Crashalot:再一次,在你的问题中更多的是艺术而不是科学。执行 JOIN 时,MongoDB 的性能不如 SQL 数据库。抓取一堆文档比检索一个大文档的性能要差得多。另一方面,如果您很少需要 JOINed 数据,则可以通过规范化数据来节省大量网络带宽(和内存)。示例:假设允许用户提供图片,如果该图片显示在每个帖子旁边,则将其存储在用户文档中是有意义的,如果它仅显示在用户的信息页面上,则将其放入单独的文件。以上是关于MongoDB:存储和何时使用关系的主要内容,如果未能解决你的问题,请参考以下文章