处理大型数据集时的快速NOSQL查询

时间:2013-12-11 09:50:32

标签: mongodb nosql

我目前正试图说服管理层我们应该将一些数据从MS SQL转移到NOSQL(可能是MongoDB)。具体来说,我想要移动的是我们的WebStats系统。目前我们在一个表中有大约1.5亿行,而且这个数据集总是在增长(我们存储了数年的统计数据。)

作为测试,我运行了以下查询1.5亿次:

  

db.test.insert({SiteId:1,PageUrl:“/ home /”,印象数:1,日期:新日期(),   IsCrawler:false,LanguageId:2057,ClientIpAddress:“1.2.3.4”,DateTime:new Date(   ),ReferalUrl:“http://www.google.com”,UniqueUserGuid:1,BrowserName:“IE”,Brow   serVersion:11,BrowserAgent:“blah”,IsAbcValid:true,hasChecked:true,connection   速度:1,国家:“英国”,地区:“米德兰兹”,城市:“考文垂”})

然后我执行一次:

  

db.test.insert({SiteId:1,PageUrl:“/ home /”,印象数:1,日期:新日期(),   IsCrawler:false,LanguageId:2057,ClientIpAddress:“1.2.3.4”,DateTime:new Date(   ),ReferalUrl:“http://www.google.com”,UniqueUserGuid:1,BrowserName:“IE”,Brow   serVersion:11,BrowserAgent:“blah”,IsAbcValid:true,hasChecked:true,connection   速度:1,国家:“美国”,地区:“纽约”,城市:“纽约”})

其次是:

  

db.test.ensureIndex({“PageUrl”:1,“Date”:1,“ClientIpAddress”:1})

索引编制完成后,我运行了以下搜索:

  

db.test.find({国家:/ S /})

它最终找到了我添加的美国文档,但它花费的时间比在MS SQL中要长。我错误地索引了这个吗?我基本上只是试图抨击可能的性能提升的演示,所以如果有人能指出我处理非常大的数据集的例子,那么我很乐意使用它。

谢谢,

3 个答案:

答案 0 :(得分:3)

您必须按国家/地区编制索引才能进行搜索。如果您不想使用这样的正则表达式,索引通常不会有帮助,除非它位于字符串的前面。

db.test.find({Country:{$regex:"^US"}})

答案 1 :(得分:1)

如果您正在国家/地区运行查询,则应创建类似db.test.ensureIndex({Country:1})的索引。

答案 2 :(得分:1)

低效查询

问题中的索引位于错误的字段上,但假设已更正,则查询仍然会很慢。

来自the docs

  

$ regex只能在正则表达式具有字符串开头(即^)的锚点时有效地使用索引,并且是区分大小写的匹配。

此查询:

  

db.test.find({国家:/ S /})

不以固定字符串开头,因此无法有效地使用索引。使用explain,可以研究这种正则表达式查询的影响,例如:

> db.test.find({Country:/S/}).explain();
{
"cursor" : "BtreeCursor Country_1 multi",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 150000000,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
    "Country" : [
        [
            "",
            {

            }
        ],
        [
            /S/,
            /S/
        ]
    ]
},
"server" : "host.local:27017"
}

请注意nscanned的{​​{3}}值。索引,但无论匹配对象的数量如何,都需要扫描整个索引。

更好的想法是确定此字段的哪些值可以匹配,并明确搜索这些值:

> db.test.find({Country:['US']}).explain();
> #                      ^ derive this list
{
"cursor" : "BtreeCursor Country_1 multi",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
    "Country" : [
        [
            "US",
            "US"
        ],
        [
            [
                "US"
            ],
            [
                "US"
            ]
        ]
    ]
},
"server" : "host.local:27017"
}

请注意,在这种情况下,nscanned的值与nscannedObjects相同 - 表示有效使用索引,可能很多更快的查询。