Mongodb - 指数较慢

时间:2014-07-12 16:28:13

标签: mongodb indexing

我在集合中有大约1000000个文档(随机生成)。

示例文件:

{
    "loc": {
        "lat": 39.828475,
        "lon": 116.273542
    },
    "phone": "",
    "keywords": [
        "big",
        "small",
        "biggest",
        "smallest"
    ],
    "prices": [
        {
            "category": "uRgpiamOVTEQ",
            "list": [
                {
                    "price": 29,
                    "name": "ehLYoPpntlil"
                }
            ]
        },
        {
            "category": "ozQNmdwpwhXPnabZ",
            "list": [
                {
                    "price": 96,
                    "name": "ITTaLHf"
                },
                {
                    "price": 88,
                    "name": "MXVgJFBgtwLYk"
                }
            ]
        },
        {
            "category": "EDkfKGZSou",
            "list": [
                {
                    "price": 86,
                    "name": "JluoCLnenOqDllaEX"
                },
                {
                    "price": 35,
                    "name": "HbmgMDfxCOk"
                },
                {
                    "price": 164,
                    "name": "BlrUD"
                },
                {
                    "price": 106,
                    "name": "LOUcsMDeaqVm"
                },
                {
                    "price": 14,
                    "name": "rDkwhN"
                }
            ]
        }
    ],
}

无索引搜索

> db.test1.find({"prices.list.price": { $gt: 190 } }).explain()
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 541098,
    "nscannedObjects" : 1005584,
    "nscanned" : 1005584,
    "nscannedObjectsAllPlans" : 1005584,
    "nscannedAllPlans" : 1005584,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 8115,
    "nChunkSkips" : 0,
    **"millis" : 13803,**
    "server" : "localhost:27017",
    "filterSet" : false
}

使用索引:

> db.test1.ensureIndex({"prices.list.price":1,"menu.list.name":1})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

> db.test1.find({"prices.list.price": { $gt: 190 } }).explain()
{
    "cursor" : "BtreeCursor prices.list.price_1_prices.list.name_1",
    "isMultiKey" : true,
    "n" : 541098,
    "nscannedObjects" : 541098,
    "nscanned" : 868547,
    "nscannedObjectsAllPlans" : 541098,
    "nscannedAllPlans" : 868547,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 16852,
    "nChunkSkips" : 0,
    **"millis" : 66227,**
    "indexBounds" : {
        "menu.list.price" : [
            [
                190,
                Infinity
            ]
        ],
        "menu.list.name" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "localhost:27017",
    "filterSet" : false
}

知道为什么索引搜索比没有索引更慢?

我也将使用:

db.test1.find({loc:{$ near:[39.876045,32.862245]}})(需要2d索引)

db.test1.find({keywords:{$ in:[“small”,“another”]}})(使用关键字索引)

db.test1.find({“prices.list.name”:/。 s。 /})(无需索引,因为我将使用正则表达式)

2 个答案:

答案 0 :(得分:4)

索引允许更快地访问满足查询的文档位置。

在您的示例中,您的查询选择集合中所有文档的一半。因此,即使索引扫描提供了更快的访问权限,知道哪些文档将与查询谓词匹配,但它实际上会创建更多的工作。

在集合扫描中,查询正在扫描所有文档,并检查您要查询的字段以查看它是否匹配。有一半时间它最终选择了文件。

在索引扫描中,查询遍历所有索引条目的一半,然后直接从它们跳转到满足查询谓词的文档。在你的情况下,这是更多的操作。

此外,在执行此操作时,操作正在产生读取互斥锁,当他们需要等待他们必须读取的文档被带入RAM时,或者当存在等待写入的写入时,以及索引扫描显示收集扫描产量的两倍。如果您的工作集没有足够的RAM,那么添加索引会对现有资源施加更多压力,使速度变慢,而不是更快。

尝试使用与价格相比较大的数字相同的查询,例如500(或者数据集中更具选择性的任何内容)。如果使用索引查询仍然较慢,那么您可能会在系统上看到大量页面错误。但是如果索引有足够的RAM,那么索引查询将很多更快,而未编制索引的查询将同样慢。

答案 1 :(得分:0)

首先,作为建议,在使用elemMatch查询数组时,您将获得更快的速度。 http://docs.mongodb.org/manual/reference/operator/query/elemMatch/ 在你的情况下

db.test1.find({"prices.list.price":{ $elemMatch: { $gte: 190 }}  })

第二件事是

  

要索引包含数组值的字段,MongoDB会添加索引项   对于数组中的每个项目。这些多键索引允许MongoDB   使用数组的值从查询中返回文档。 MongoDB的   如果是,则自动确定是否创建多键索引   索引字段包含数组值;你不需要明确   指定多键类型。

     

考虑下面的多键索引说明:   enter image description here

     

addr.zip字段上的多键索引图。 addr字段包含一个数组   地址文件。地址文档包含zip字段。

     

Multikey索引支持其他MongoDB支持的所有操作   指标;但是,应用程序可能会使用多键索引进行选择   基于数组值的值范围的文档。   多键索引支持包含两个值的数组(例如字符串,   数字)和嵌套文件。

     

来自http://docs.mongodb.org/manual/core/index-multikey/