mongoid 索引仍然导致 COLLSCAN
Posted
技术标签:
【中文标题】mongoid 索引仍然导致 COLLSCAN【英文标题】:mongoid index still resulting in a COLLSCAN 【发布时间】:2021-01-22 22:43:06 【问题描述】:我有一个带有简单索引的简单类
class A
include Mongoid::Document
field :value
index(value: 1)
在命令行,我重新索引
bundle exec rake db:mongoid:remove_indexes
bundle exec rake db:mongoid:create_indexes
但是当我在 rails 控制台中运行一个简单的查询时
A.where(value: "1").to_a
mongodb 日志清楚地显示了一个 COLLSCAN
command test_development.a command: find find: "a", filter: value: "1" ,
$db: "test_development", lsid: id: UUID("fa470127-398a-4f06-9a17-57b058017cf7")
planSummary: COLLSCAN keysExamined:0 docsExamined:816688 cursorExhausted:1
numYields:6380 nreturned:0
我做错了什么?
更新 - 添加附加信息:
db.case_data.getIndexSpecs()
[
"v" : 2,
"key" :
"_id" : 1
,
"name" : "_id_",
"ns" : "simple_development.case_data"
,
"v" : 2,
"key" :
"_fts" : "text",
"_ftsx" : 1
,
"name" : "value_text",
"ns" : "simple_development.case_data",
"weights" :
"value" : 1
,
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
]
解释的输出:
db.case_data.find(value: "test").explain()
"queryPlanner" :
"plannerVersion" : 1,
"namespace" : "simple_development.case_data",
"indexFilterSet" : false,
"parsedQuery" :
"value" :
"$eq" : "test"
,
"queryHash" : "7E4E9C25",
"planCacheKey" : "7E4E9C25",
"winningPlan" :
"stage" : "COLLSCAN",
"filter" :
"value" :
"$eq" : "test"
,
"direction" : "forward"
,
"rejectedPlans" : [ ]
,
"serverInfo" :
"host" : "msc-2",
"port" : 27017,
"version" : "4.2.8",
"gitVersion" : "43d25964249164d76d5e04dd6cf38f6111e21f5f"
,
"ok" : 1
【问题讨论】:
验证索引是否已创建,包括当前的索引列表,并包含一个完整且可读的查询计划。 你能帮我理解“当前索引列表”以及我如何获得查询计划,只是 .explain 吗? 我认为这不是一个问题。你能在 mongo-shell 中添加以下命令的结果吗:db.getCollection(<collection_name>).getIndexSpecs()
以及db.getCollection(<collection_name>).find(value: "1").explain()
的结果它将理解这个问题
@UdiCohen 添加了请求的信息。查询需要大约 15 秒 b/c 它必须通过 800K 记录,希望这会有所帮助
【参考方案1】:
我不知道为什么会这样创建索引,可能是因为您没有在模型类中指定字段的类型。尝试指定字段的类型,然后在 mongo shell db.getCollection('X').dropIndex('value_text')
中手动删除索引,然后运行 rake 创建索引rake db:create_indexes
。
如果这不起作用,我会删除索引并在 mongo shell db.getCollection('X').createIndex('value': 1, name: 'value_1', background: true)
中手动创建一个(或等待更好的答案?)
【讨论】:
我试图在没有指定类型的情况下定义一个字段,并且索引是按预期创建的,所以可能是 mongoid 版本问题(我使用版本 7.1)【参考方案2】:在 Mongoid 7.1.1 和 mongodb 4.2.9 的某些组合中,rake 任务和 mongorestore 都不会真正重新创建索引。他们说有,但没有。
此命令导致 COLLSCAN:
bundle exec rake db:mongoid:remove_indexes
bundle exec rake db:mongoid:create_indexes
使用 mongo 控制台创建索引,或者在每个模型中,在 Rails 控制台中,做:
A.remove_indexes
A.create_indexes
导致没有 COLLSCAN。
我已经用干净的数据库恢复科学地重复了这一点,并且可以肯定地说 rake 命令和 mongorestore 命令不会重新创建索引。我上面的解决方案解决了这个问题。
感谢大家的帮助, 凯文
【讨论】:
jira.mongodb.org/browse/…更新rails版本。以上是关于mongoid 索引仍然导致 COLLSCAN的主要内容,如果未能解决你的问题,请参考以下文章
mongoid 中的索引:我应该何时以及多久运行一次 rake db:mongoid:create_indexes?
在非 Rails 环境中通过 Mongoid 创建 MongoDB 索引
Mongoid 3 + Heroku (MongoHQ) 导致 Moped::Errors::OperationFailure