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?

使用 mongoid 查看 MongoDB 中的现有索引

在非 Rails 环境中通过 Mongoid 创建 MongoDB 索引

Mongoid 3 + Heroku (MongoHQ) 导致 Moped::Errors::OperationFailure

rails mongoid中的多键索引

Rails,mongoid,heroku 性能