mongodb - 为什么添加索引会降低性能?

标签 mongodb indexing nosql

我正在评估以下查询的性能。

db.products_old.find({ regularPrice: { $lte: 200 } })

该集合有超过一百万个文档,总共约 0.15GB。


无索引

这是预料之中的。必须进行全列扫描

"executionTimeMillis" : 1019,

<子>

"winningPlan" : {
    "stage" : "COLLSCAN",
    "filter" : {
        "regularPrice" : {
            "$lte" : 200
        }
    },
    "direction" : "forward"
},

索引{ regularPrice: 1 }

"executionTimeMillis" : 2842,

<子>

"winningPlan" : {
    "stage" : "FETCH",
    "inputStage" : {
        "stage" : "IXSCAN",
        "keyPattern" : {
            "regularPrice" : 1
        },
        "indexName" : "regularPrice_1",
        "isMultiKey" : false,
        "multiKeyPaths" : {
            "regularPrice" : [ ]
        },
        "isUnique" : false,
        "isSparse" : false,
        "isPartial" : false,
        "indexVersion" : 2,
        "direction" : "forward",
        "indexBounds" : {
            "regularPrice" : [
                "[-inf.0, 200.0]"
            ]
        }
    }
},

现在它使用了索引,但是执行时间明显变差了。 为什么?

此外,如果性能更差,为什么 Mongo 不使用 COLLSCAN 使用会减慢执行速度的索引? rejectedPlans 为空,这表明甚至没有考虑其他计划。为什么?


Here's完整的 allPlansExecution 输出。

最佳答案

在执行COLLSCAN 时,MongoDB 正在从存储驱动器中读取并将匹配的文档存储在RAM 中以备后用。另一方面,IXSCAN 读取存储索引数据的索引和指向它们在存储驱动器上的位置的指针。 (Here's a nice visualisation 从幻灯片 6 到幻灯片 20 左右)

您的集合中有很多文档,但您的索引中也有很多匹配的文档。存储在存储驱动器上的数据并没有以最好的方式存储(就像在索引中一样),所以当 IXSCAN 返回指向它为您的查询找到的 220k+ 文档的指针时, FETCH 需要以随机访问方式从存储驱动器读取 220k+ 次。这很慢。另一方面,我假设 COLLSCAN 正在执行顺序读取,这可能是逐页完成的,并且比 FETCH 读取快得多。

所以总结一下:不是索引让你慢下来,而是 FETCH 阶段。如果你仍然想使用这个索引并有一个更快的查询执行时间,然后使用 .select('-_id regularPrice') 这将只是添加一个快速的 PROJECTION 阶段和从索引中读取所有必需的字段。或者,如果您需要 _id,则添加索引 {regularPrice: 1, _id: 1}

关于 为什么 Mongo 使用索引的部分,即使它知道集合扫描更快:好吧,我认为如果它看到索引,它就会使用它。但是你可以force it to use collection scan通过使用传递给它的 {natural: 1}hint 方法。

关于mongodb - 为什么添加索引会降低性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52243916/

相关文章:

mongodb - Mongo 使用带排序的索引

mongodb - 在两个不同的集合中生成重复的 Mongo ObjectId 的可能性?

java - 使用 LDT 时出现子记录错误

nosql - 如何使用 Redis 列表来实现聊天系统?

.net - 在 .NET 中使用哪些好的倒排索引库?

python - PyMongo 游标以最快的方式列出可能

mongodb - NoSQL(文档)- 引入新集合的充分理由是什么?

arrays - Mongodb 根据另一个数组元素过滤数组

mysql - (Why) MySQL 不能在这种情况下使用索引吗?

performance - SQL 2008r2 将索引更改为索引查找而不是索引扫描