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
是根据key
和sort
来创建索引名称。
key
又是什么东西呢?我们看看createIndex
的语法:
字段 | 类型 |
---|---|
keys | document |
options | document |
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 }
现在我们创建一个unique
和partialFilterExpression
结合使用的索引:
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 } )
参考地址:
上一篇: spark处理较复杂的log日志文件