monggo索引优化

mongodb索引规则

mongodb索引规则基本上与传统的关系库一样,大部分优化MySQL/Oracle/SQLite索引的技巧也适用于mongodb。

为什么用索引

  • 当查询中用到某些条件时,可以对该键建立索引,以提高查询速度。
  • 数据量多且查询多余更新时,可以用索引提高查询速度。

废话不多说,先上图,后再说

  • 表总数据2000万+
    jdk

  • 查询表索引情况
    jdk

  • 查询在没有建立索引情况下执行
    jdk

  • 对需要过滤字段建立索引(此时数据库拥有2000万+数据,执行时间89s)
    jdk

  • 查询表索引情况(已建立)
    jdk

  • 查询在建立了索引情况下执行
    jdk

    (^▽^)建立了索引查询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()

删除索引

//删除单个
db.launcher4k20170628.dropIndex('name')

//删除全部
db.launcher4k20170628.dropIndex('*')

使用explain

explain是非常有用的工具,会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。explain会返回一个文档,而不是游标本身。如:
jdk
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()));
    }

jdk

  • 创建单列索引
    /**
    * 添加索引
    * @param string
    */
    @SuppressWarnings("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));
    }

注意:在测试创建索引是否成功我手动去删了库,然后执行创建索引就创建无效。但是如果新创建表为其创建索引的,就会生成索引值。

jdk

[mongoTemplate参考文档地址]

转载请注明出处:[www.updatecg.xin]

文章作者: 陈 武
文章链接: http://www.updatecg.xin/2017/09/23/monggo索引优化/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 我的学习记录
打赏
  • 微信
  • 支付寶

评论