从MongoDB
文档中提到:
当您只需要文档中的一部分字段时,您可以通过仅返回您需要的字段来获得更好的性能
过滤字段如何影响性能?性能是否与通过网络传输的数据大小有关?或将保存在内存中的数据大小?这种性能究竟是如何提高的?文档中提到的这种性能是什么?
我的 MongoDB 查询很慢。返回子集是否会影响我的慢查询(我在该字段上有复合索引)?
从MongoDB
文档中提到:
当您只需要文档中的一部分字段时,您可以通过仅返回您需要的字段来获得更好的性能
过滤字段如何影响性能?性能是否与通过网络传输的数据大小有关?或将保存在内存中的数据大小?这种性能究竟是如何提高的?文档中提到的这种性能是什么?
我的 MongoDB 查询很慢。返回子集是否会影响我的慢查询(我在该字段上有复合索引)?
默认情况下,查询返回匹配文档中的所有字段。如果您需要所有字段,则返回完整文档将比让服务器使用投影标准处理结果集更有效。
但是,使用投影来限制从查询结果返回的字段可以通过以下方式提高性能:
当使用投影删除未使用的字段时,MongoDB 服务器必须将每个完整文档提取到内存中(如果它不存在)并过滤结果以返回。这种投影的使用不会减少 MongoDB 服务器上的内存使用或工作集,但可以根据您的数据模型和投影字段为查询结果节省大量网络带宽。
覆盖查询是一种特殊情况,查询结果中的所有请求字段都包含在使用的索引中,因此服务器不必获取完整文档。覆盖查询可以提高性能(通过避免获取文档)和内存使用(如果其他查询不需要获取相同的文档)。
例子
为了通过
mongo
shell 进行演示,假设您有一个如下所示的文档:该字段
b
可能表示值的选择(或者在这种情况下是一个非常长的字符串)。接下来,创建一个索引,
{a:1}
该索引是您的用例查询的常用字段:一个没有投影条件的简单
findOne()
函数返回一个大约 10MB 的查询结果:添加投影
{a:1}
将限制输出到字段a
和文档_id
(默认包含)。MongoDB 服务器仍在操作一个 10MB 的文档来选择两个字段,但查询结果现在只有 33 个字节:未涵盖此查询,因为必须获取完整文档才能发现该
_id
值。该_id
字段默认包含在查询结果中,因为它是文档的唯一标识符,但_id
除非明确添加,否则不会包含在二级索引中。结果中的
totalDocsExamined
和totalKeysExamined
指标explain()
将显示检查了多少文档和索引键:可以使用投影来改进此查询以排除字段并仅使用索引
_id
实现覆盖查询。{a:1}
覆盖的查询不再需要将约 10MB 的文档提取到内存中,因此在网络和内存使用方面都很有效:如果没有特定查询的上下文、示例文档和完整的解释输出,这是无法回答的。但是,您可以在自己的环境中为相同的查询运行一些基准测试,使用和不使用投影来比较结果。如果您的预测在整体查询执行时间(处理和传输结果)上增加了显着开销,这可能强烈暗示您的数据模型可以改进。
如果不清楚查询速度慢的原因,最好发布一个包含具体细节的新问题以进行调查。
通过投影,可以实现结果集直接来自索引的情况。
如果您有
{x:1, y:1, z:1}
x、y、z 都不是 _id 的复合索引,则需要进行投影{_id:0, x:1, y:1, z:1}
,因为_id
它总是作为结果集的一部分返回(当它没有被投影时)并且引擎需要读取数据文件来获取它。这是因为,索引没有 _id 的值,只有指向存储值的文档的指针。