mongodb索引规则
mongodb索引规则基本上与传统的关系库一样,大部分优化MySQL/Oracle/SQLite索引的技巧也适用于mongodb。
为什么用索引
- 当查询中用到某些条件时,可以对该键建立索引,以提高查询速度。
- 数据量多且查询多余更新时,可以用索引提高查询速度。
废话不多说,先上图,后再说
表总数据2000万+
查询表索引情况
查询在没有建立索引情况下执行
对需要过滤字段建立索引(此时数据库拥有2000万+数据,执行时间89s)
查询表索引情况(已建立)
查询在建立了索引情况下执行
(^▽^)建立了索引查询2000万数据速度从30秒减少到1毫秒,这效率牛逼了!
注意:建立索引尽量在创建表时创建,不然当表数据过大,创建索引会消耗大量时间和cpu
有点影响,但是不大
当然使用索引是也是有代价的:对于添加的每一条索引,每次写操作(插入、更新、删除)都将耗费更多的时间。这是因为,当数据发生变化时,不仅要更新文档,还要更新级集合上的所有索引。因此,mongodb限制每个集合最多有64个索引。
常用操作
唯一索引
db.launcher4k20170628.ensureIndex({"name":1},{"unique":true}) |
单列索引
db.launcher4k20170628.ensureIndex({positionCode:1},{name:'positionCode_index'}) |
复合索引
索引的值是按一定顺序排列的,所以使用索引键对文档进行排序非常快。db.launcher4k20170628.ensureIndex({positionCode:1,launcherType:1},{name:'position_index'})
查看我们建立的索引
db.launcher4k20170628.getIndexes() |
删除索引
//删除单个 |
使用explain
explain是非常有用的工具,会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。explain会返回一个文档,而不是游标本身。如:
explain会返回查询使用的索引情况,耗时和扫描文档数的统计信息。
项目实践
统计功能,每天凌晨定时从mongo统计数据到mysql。但是随着数据量增大,最高数据达到9000万+数据,要对这如此庞大数据进行统计,避免不了使用索引以及mongo聚合函数。
因之前没有添加索引,造成了一诸多问题。例如之前文章中提到的[MongoDB 查询超时异常 SocketTimeoutException]
经常造成连接池杠不住,以及查询时长过长造成连接不上monggo等问题。org.springframework.dao.DataAccessResourceFailureException: Read operation to server 172.23.5.7:9343 failed on database launcher4k;
nested exception is com.mongodb.MongoException$Network: Read operation to server 172.23.5.7:9343 failed on database launcher4k
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:59)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1926)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:396)
at org.springframework.data.mongodb.core.MongoTemplate.executeCommand(MongoTemplate.java:336)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1425)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1360)
at com.amt.modules.dao.OprationDaoImpl.getCountsTime(OprationDaoImpl.java:123)
at com.amt.modules.service.OprationServiceImpl.saveCountsTime(OprationServiceImpl.java:379)
at com.amt.modules.common.ContentTaskMethod.moveDateMongoToMysql(ContentTaskMethod.java:56)
at com.amt.modules.common.SystemTask.createStatisticData(SystemTask.java:45)
at sun.reflect.GeneratedMethodAccessor2305.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
可以通过配置mongo文件进行优化,但这不是长远之计。mongo.connectionsPerHost=8
mongo.threadsAllowedToBlockForConnectionMultiplier=4
mongo.connectTimeout=1000
mongo.maxWaitTime=2000 //最大连接时长 秒为单位
mongo.autoConnectRetry=true
mongo.socketKeepAlive=true
mongo.socketTimeout=0
mongo.slaveOk=true
这就需要索引来大大的调高查询速度
- 创建联合索引
//方法过时了
private void createIndex(String name){
IndexOperations io=mongoTemplate.indexOps(name);
Index index =new Index();
index.on("positionCode",Order.ASCENDING);
index.on("positionName",Order.ASCENDING);
index.on("launcherType",Order.ASCENDING);
index.on("terminalId",Order.ASCENDING);
index.on("labelId",Order.ASCENDING);
io.ensureIndex(index);
}
//正常
private void createIndex(String name){
DBObject indexOptions = new BasicDBObject();
indexOptions.put("positionCode", 1);
indexOptions.put("positionName", 1);
indexOptions.put("launcherType.d", 1);
indexOptions.put("labelId", 1);
CompoundIndexDefinition indexDefinition =new CompoundIndexDefinition(indexOptions);
mongoTemplate.indexOps(name).ensureIndex(indexDefinition);
}
public void create(OprationEntity opration) throws Exception {
mongoTemplate.insert(opration, getTableName(opration.getUpdateTime()));
this.createIndex(getTableName(opration.getUpdateTime()));
}
- 创建单列索引
/**
* 添加索引
* @param string
*/
"deprecation") (
private void createIndex(String name){
IndexOperations io=mongoTemplate.indexOps(name);
io.ensureIndex(new Index().on("positionCode", Order.ASCENDING));
io.ensureIndex(new Index().on("positionName", Order.ASCENDING));
io.ensureIndex(new Index().on("launcherType", Order.ASCENDING));
io.ensureIndex(new Index().on("labelId", Order.ASCENDING));
}
注意:在测试创建索引是否成功我手动去删了库,然后执行创建索引就创建无效。但是如果新创建表为其创建索引的,就会生成索引值。
转载请注明出处:[www.updatecg.xin]