草庐IT

javascript - mongodb -- count() 比 find() 慢多少?

coder 2023-11-01 原文

我正在使用 mongoose 来计算与特定查询匹配的文档数量。我对该查询的索引是:{createdAt: -1, status: -1, oId: -1}

Mongo版本为3.2,馆藏文档量约175万。

如果我这样做:

model.find({
                        createdAt: {'$gte': threeMonths, '$lt': today},
                        status: {'$in': model.STATUS_SET}
                    }).select({_id: 0, status: 1}).count().then((c) => result[alias] = c)

这需要超过 2 分钟。但如果我这样做:

model.find({
                createdAt: {'$gte': threeMonths, '$lt': today},
                status: {'$in': model.STATUS_SET}
            }).select({_id: 0, status: 1}).lean().then((c) => result[alias] = c.length)

然后大约需要 2.5 秒。

我做错了什么?我可以做些什么来加快速度?

编辑:解释日志。

计数:

"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 0,
		"executionTimeMillis" : 82671,
		"totalKeysExamined" : 1749689,
		"totalDocsExamined" : 1643722,
		"executionStages" : {
			"stage" : "COUNT",
			"nReturned" : 0,
			"executionTimeMillisEstimate" : 80960,
			"works" : 1750066,
			"advanced" : 0,
			"needTime" : 1749689,
			"needFetch" : 376,
			"saveState" : 14662,
			"restoreState" : 14662,
			"isEOF" : 1,
			"invalidates" : 0,
			"nCounted" : 1643722,
			"nSkipped" : 0,
			"inputStage" : {
				"stage" : "FETCH",
				"nReturned" : 1643722,
				"executionTimeMillisEstimate" : 80890,
				"works" : 1750065,
				"advanced" : 1643722,
				"needTime" : 105967,
				"needFetch" : 376,
				"saveState" : 14662,
				"restoreState" : 14662,
				"isEOF" : 1,
				"invalidates" : 0,
				"docsExamined" : 1643722,
				"alreadyHasObj" : 0,
				"inputStage" : {
					"stage" : "IXSCAN",
					"nReturned" : 1643722,
					"executionTimeMillisEstimate" : 3800,
					"works" : 1749689,
					"advanced" : 1643722,
					"needTime" : 105967,
					"needFetch" : 0,
					"saveState" : 14662,
					"restoreState" : 14662,
					"isEOF" : 1,
					"invalidates" : 0,
					"keyPattern" : {
						"createdAt" : -1,
						"status" : -1,
						"oId" : -1
					},
					"indexName" : "moderatedContent",
					"isMultiKey" : false,
					"direction" : "forward",
					"indexBounds" : {
						"createdAt" : [
							"(new Date(1467195213000), new Date(1459246413000)]"
						],
						"status" : [
							"[\"UNDECIDED\", \"UNDECIDED\"]",
							"[\"APPROVED\", \"APPROVED\"]"
						],
						"oId" : [
							"[MaxKey, MinKey]"
						]
					},
					"keysExamined" : 1749689,
					"dupsTested" : 0,
					"dupsDropped" : 0,
					"seenInvalidated" : 0,
					"matchTested" : 0
				}
			}
		},
		"allPlansExecution" : [ ]
	}

用于查找。

"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 1643722,
		"executionTimeMillis" : 1216,
		"totalKeysExamined" : 1749689,
		"totalDocsExamined" : 0,
		"executionStages" : {
			"stage" : "PROJECTION",
			"nReturned" : 1643722,
			"executionTimeMillisEstimate" : 1080,
			"works" : 1749690,
			"advanced" : 1643722,
			"needTime" : 105967,
			"needFetch" : 0,
			"saveState" : 13669,
			"restoreState" : 13669,
			"isEOF" : 1,
			"invalidates" : 0,
			"transformBy" : {
				"_id" : 0,
				"status" : 1
			},
			"inputStage" : {
				"stage" : "IXSCAN",
				"nReturned" : 1643722,
				"executionTimeMillisEstimate" : 920,
				"works" : 1749690,
				"advanced" : 1643722,
				"needTime" : 105967,
				"needFetch" : 0,
				"saveState" : 13669,
				"restoreState" : 13669,
				"isEOF" : 1,
				"invalidates" : 0,
				"keyPattern" : {
					"createdAt" : -1,
					"status" : -1,
					"oId" : -1
				},
				"indexName" : "moderatedContent",
				"isMultiKey" : false,
				"direction" : "forward",
				"indexBounds" : {
					"createdAt" : [
						"(new Date(1467195213000), new Date(1459246413000)]"
					],
					"status" : [
						"[\"UNDECIDED\", \"UNDECIDED\"]",
						"[\"APPROVED\", \"APPROVED\"]"
					],
					"oId" : [
						"[MaxKey, MinKey]"
					]
				},
				"keysExamined" : 1749689,
				"dupsTested" : 0,
				"dupsDropped" : 0,
				"seenInvalidated" : 0,
				"matchTested" : 0
			}
		}
	}

对于游标中第一个带有 .explain() 的帖子:

"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 0,
		"executionTimeMillis" : 89191,
		"totalKeysExamined" : 1749689,
		"totalDocsExamined" : 1643722,
		"executionStages" : {
			"stage" : "COUNT",
			"nReturned" : 0,
			"executionTimeMillisEstimate" : 83400,
			"works" : 1751709,
			"advanced" : 0,
			"needTime" : 1749689,
			"needFetch" : 2019,
			"saveState" : 15648,
			"restoreState" : 15648,
			"isEOF" : 1,
			"invalidates" : 0,
			"nCounted" : 1643722,
			"nSkipped" : 0,
			"inputStage" : {
				"stage" : "FETCH",
				"nReturned" : 1643722,
				"executionTimeMillisEstimate" : 83260,
				"works" : 1751708,
				"advanced" : 1643722,
				"needTime" : 105967,
				"needFetch" : 2019,
				"saveState" : 15648,
				"restoreState" : 15648,
				"isEOF" : 1,
				"invalidates" : 0,
				"docsExamined" : 1643722,
				"alreadyHasObj" : 0,
				"inputStage" : {
					"stage" : "IXSCAN",
					"nReturned" : 1643722,
					"executionTimeMillisEstimate" : 8290,
					"works" : 1749689,
					"advanced" : 1643722,
					"needTime" : 105967,
					"needFetch" : 0,
					"saveState" : 15648,
					"restoreState" : 15648,
					"isEOF" : 1,
					"invalidates" : 0,
					"keyPattern" : {
						"createdAt" : -1,
						"status" : -1,
						"oId" : -1
					},
					"indexName" : "moderatedContent",
					"isMultiKey" : false,
					"direction" : "forward",
					"indexBounds" : {
						"createdAt" : [
							"(new Date(1467195213000), new Date(1459246413000)]"
						],
						"status" : [
							"[\"UNDECIDED\", \"UNDECIDED\"]",
							"[\"APPROVED\", \"APPROVED\"]"
						],
						"oId" : [
							"[MaxKey, MinKey]"
						]
					},
					"keysExamined" : 1749689,
					"dupsTested" : 0,
					"dupsDropped" : 0,
					"seenInvalidated" : 0,
					"matchTested" : 0
				}
			}
		}
	}

最佳答案

你的答案的关键是

//count
"totalDocsExamined" : 1643722,

对比

//find
"totalDocsExamined" : 0,

查找查询完全在索引上运行,不读取任何单个文档,而计数查询实际上从数据库中读取每个文档。

原因是,您的查找查询使用了 lean() 选项。据 Mongoose doc :

Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or other Mongoose magic applied.

最重要的是,在您的精益查找查询中,您只是 select()ing idstatus,这似乎是预计的("transformBy"...) 这样整个查询就变成了一个 covered query 并且无需阅读任何文档即可满足请求。

关于javascript - mongodb -- count() 比 find() 慢多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38097190/

有关javascript - mongodb -- count() 比 find() 慢多少?的更多相关文章

  1. ruby - 可以通过多少种方法将方法添加到 ruby​​ 对象? - 2

    当谈到运行时自省(introspection)和动态代码生成时,我认为ruby​​没有任何竞争对手,可能除了一些lisp方言。前几天,我正在做一些代码练习来探索ruby​​的动态功能,我开始想知道如何向现有对象添加方法。以下是我能想到的3种方法:obj=Object.new#addamethoddirectlydefobj.new_method...end#addamethodindirectlywiththesingletonclassclass这只是冰山一角,因为我还没有探索instance_eval、module_eval和define_method的各种组合。是否有在线/离线资

  2. ruby-on-rails - ActiveRecord 的 find_or_create* 方法是否存在根本性缺陷? - 2

    有几种方法:first_or_create_by、find_or_create_by等,它们的工作原理是:与数据库对话以尝试找到我们想要的东西如果我们找不到,就自己做保存到数据库显然,并发调用这些方法可能会使两个线程都找不到它们想要的东西,并且在第3步中一个线程会意外失败。似乎更好的解决方案是,创建或查找即:提前在您的数据库中创建合理的唯一性约束。如果你想保存一些东西,就保存它如果有效,那就太好了。如果它因为RecordNotUnique异常而无法工作,它已经存在,太好了,加载它那么在什么情况下我想使用Rails内置的东西而不是我自己的(看起来更可靠)create_or_find?

  3. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  4. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  5. ruby-on-rails - 以 DRY 方式覆盖 ActiveRecord 中的 "find" - 2

    我有一些模型需要在它们上面放置自定义查找条件。例如,如果我有一个联系人模型,每次调用Contact.find时,我都想限制返回的联系人只属于正在使用的帐户。我通过Google找到了这个(我对其进行了一些自定义):defself.find(*args)with_scope(:find=>{:conditions=>"account_id=#{$account.id}"})dosuper(*args)endend这很好用,除了少数情况下account_id不明确,所以我将其调整为:defself.find(*args)with_scope(:find=>{:conditions=>"#{s

  6. ruby-on-rails - rails : Find tasks that were created on a certain day? - 2

    我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio

  7. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  8. ruby-on-rails - find_all 数组中符合条件的元素? - 2

    我有一个哈希条目数组,并希望根据传递给函数的参数进行过滤。如果散列中有三个值,A、B和C,我想做类似的事情:data=[{A:'a1',B:'b1',C:'c1'},{A:'a1',B:'b2',C:'c1'},{A:'a1',B:'b2',C:'c2'},{A:'a2',B:'b1',C:'c1'},{A:'a2',B:'b2',C:'c1'}]data.find_all{|d|d[:A].include?params[:A]}.find_all{|d|d[:B].include?params[:B]}.find_all{|d|d[:C].include?params[:C]}找到所

  9. ruby-on-rails - "Could not find generator figaro:install" - 2

    我正在使用来自learn-rails.com的“学习RubyOnRails”pdf书。我在第13章“配置”。我们应该在哪里执行命令:“railsgeneratefigaro:install”在第12章中,我们安装了figarogem:“我们已经在Gemfile中安装了figarogem并运行bundleinstall。”当我运行该命令时,我得到:“找不到生成器figaro:install。”我开始搜索类似的问题,我确实在这里找到了这个问题:railsgenerate-"Couldnotfindgenerator"他们被建议在命令中也包含“迁移”。我将它包含在我的命令中并让它做某事,但我

  10. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

随机推荐