mongodb 创建局部索引【Partial Indexes】

环境

mongodb:3.4
工具:Robo 3T1.1

前言

还是前几天的问题: mongodb中$nin操作的优化

今天在调相关接口时,第一次还是慢的出不来,之前我说把$nin换成$gt,但是效果依旧不理想。

今天看官网文档时,发现了好东西Partial Indexes
这个是,mongodb3.2增加的特性。

实战

先说下我的业务情况。

这里写图片描述

我这个接口需要拿的数据如上图;

由于摘要字段 的字符很长,所以无法对该字段创建有效的索引(ir_urlcontent:1不能创建);
我的查询语句:

db.urlcontents.count({ir_groupname:"产业热点", ir_urlcontent:{$gt:""}})

说明:

假设没有创建局部索引(Partial Indexes)的话,并且数据库总量是72万,查询时间大概需要10s以上。
说明下,已经创建了ir_groupname_1_ir_urltime_-1_ir_urltitle_1这样的索引,ir_urlcontent因为字符太长,无法创建索引(ir_urlcontent: 1)。

创建局部索引

db.urlcontents.createIndex({ir_groupname:1, ir_urltime:-1},
                           {partialFilterExpression:{ir_urlcontent:{$gt:""}}},
                           {background:1})

之后再执行,时间变成了4s左右。

这里写图片描述

可以看出,效果相比之前10s是好多啦!
但是4s,其实依旧很慢啦!

目前我就优化到这!

局部索引的语法

Partial Index 并不是每个命令都支持的!

支持的表达式:

$eq
$gt,$gte,$lt,$lte
$type
$and 只用于顶级操作

也就是partialFilterExpression中所支持的表达式;

创建的语句类似于上面的:

db.urlcontents.createIndex({ir_groupname:1, ir_urltime:-1},
                           {partialFilterExpression:{ir_urlcontent:{$gt:""}}},
                           {background:1})

这样的形式;

其实很简单,不多讲了

限制

拿上面的例子来说,假设现在我又想创建一个这样的索引:

db.urlcontents.createIndex({ir_groupname:1, ir_urltime:-1},
                           {partialFilterExpression:{ir_urltime:{$gt:""}}},
                           {background:1})

和上面的区别在于partialFilterExpression表达式中的ir_urlcontent字段换成了ir_urltime字段。

执行后会提示错误:

{
    "raw" : {
        "shard1/10.6.11.122:27018" : {
            "ok" : 0.0,
            "errmsg" : "Index with name: ir_groupname_1_ir_urltime_-1 already exists with different options",
            "code" : 85,
            "codeName" : "IndexOptionsConflict",
            "$gleStats" : {
                "lastOpTime" : {
                    "ts" : Timestamp(1517820607, 650),
                    "t" : NumberLong(4)
                },
                "electionId" : ObjectId("7fffffff0000000000000004")
            }
        }
    },
    "code" : 85,
    "ok" : 0.0,
    "errmsg" : "{ shard1/10.6.11.122:27018: \"Index with name: ir_groupname_1_ir_urltime_-1 already exists with different options\" }"
}

提示上也说了,该索引已经存在了!

换句话说:不能创建,仅因为过滤器表达式不同的索引

其实从索引名称就可以看出:
我们看下之前我们创建的局部索引:

    {
        "v" : 2,
        "key" : {
            "ir_groupname" : 1.0,
            "ir_urltime" : -1.0
        },
        "name" : "ir_groupname_1_ir_urltime_-1",
        "ns" : "gg_stock_db.urlcontents",
        "partialFilterExpression" : {
            "ir_urlcontent" : {
                "$gt" : ""
            }
        }
    }

看到name部分,其值为ir_groupname_1_ir_urltime_-1;也就是说,mongodb是根据keysort来创建索引名称。

key又是什么东西呢?我们看看createIndex的语法:

字段类型
keysdocument
optionsdocument

document我们的实际写法就是json字符串。

db.urlcontents.createIndex({ir_groupname:1, ir_urltime:-1}, <注意>---keys </注意>
                           {partialFilterExpression:{ir_urltime:{$gt:""}}},<注意>---options</注意>
                           {background:1}) <注意>--- options</注意>

也就是说,不管创建什么索引,keys部分都不能相同,否则就当做重复索引,不让创建。

和Unique结合做唯一限制

这里我就翻译下官方文档:

假设我们现在有这样一个集合数据:

{ "_id" : ObjectId("56424f1efa0358a27fa1f99a"), "username" : "david", "age" : 29 }
{ "_id" : ObjectId("56424f37fa0358a27fa1f99b"), "username" : "amanda", "age" : 35 }
{ "_id" : ObjectId("56424fe2fa0358a27fa1f99c"), "username" : "rajiv", "age" : 57 }

现在我们创建一个uniquepartialFilterExpression结合使用的索引:

db.users.createIndex(
   { username: 1 },
   { unique: true, partialFilterExpression: { age: { $gte: 21 } } }
)

假设我们要执行如下命令时,都会失败:

db.users.insert( { username: "david", age: 27 } )
db.users.insert( { username: "amanda", age: 25 } )
db.users.insert( { username: "rajiv", age: 32 } )

因为被我们刚刚创建的那个索引给限制了!
具体分析就是:

username:”david”,数据库中已经有一条age:29的记录,所以再插入age:27时,被局部唯一性索引所限制,所以

但是如果我们执行如下操作的话,则会成功:

db.users.insert( { username: "david", age: 20 } )
db.users.insert( { username: "amanda" } )
db.users.insert( { username: "rajiv", age: null } )

参考地址:

https://docs.mongodb.com/manual/core/index-partial/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值