【问题标题】:mongoid index still resulting in a COLLSCANmongoid 索引仍然导致 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 记录,希望这会有所帮助

标签: ruby-on-rails mongodb mongoid


【解决方案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 命令不会重新创建索引。我上面的解决方案解决了这个问题。

感谢大家的帮助, 凯文

【讨论】:

猜你喜欢
  • 2016-03-24
  • 2019-04-13
  • 2012-05-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多