1. 批量保存优化

避免一条一条查询,采用bulkWrite, 基于ReplaceOneModel,启用upsert:

 public void batchSave(List<?> spoTriples, KgInstance kgInstance) {
MongoConverter converter = mongoTemplate.getConverter();
List<ReplaceOneModel<Document>> bulkOperationList = spoTriples.stream()
.map(thing -> {
org.bson.Document dbDoc = new org.bson.Document();
converter.write(thing, dbDoc);
ReplaceOneModel<org.bson.Document> replaceOneModel = new ReplaceOneModel(
Filters.eq(UNDERSCORE_ID, dbDoc.get(UNDERSCORE_ID)),
dbDoc,
new UpdateOptions().upsert(true));
return replaceOneModel;
})
.collect(Collectors.toList());
mongoTemplate.getCollection(getCollection(kgInstance)).bulkWrite(bulkOperationList);
}

2. 分页优化

经常用于查询的字段,需要确保建立了索引。

对于包含多个键的查询,可以创建符合索引。

2.1 避免不必要的count

查询时,走索引,速度并不慢,但是如果返回分页Page<?>,需要查询totalcount,当单表数据过大时,count会比较耗时,但是设想意向,你真的需要准确的数字吗?

在google、百度等搜索引擎搜索关键词时,只会给你有限的几个结果,因此,我们也不必给出准确的数字,设定一个阈值,比如1万,当我们发现总量大于1万时,返回1万,前端显示大于1万条即可。

原理也很鉴定啊,我们skip掉MAX_PAGE_COUNT,看是否还有数据,如果有就说明总量大于MAX_PAGE_COUNT,返回MAX_PAGE_COUNT即可,否则,计算真正的count。



int MAX_PAGE_COUNT = 10000;

/**
* 当总数大于阈值时,不再计算总数
*
* @param mongoTemplate
* @param query
* @param collectionName
* @return
*/
private long count(MongoTemplate mongoTemplate, Query query, String collectionName) {
query = query.with(PageRequest.of(MAX_PAGE_COUNT, 1));
if (mongoTemplate.find(query, Thing.class, collectionName).size() > 0) {
return MAX_PAGE_COUNT;
}
return mongoTemplate.count(query, collectionName);
}

前端显示:

2.2 避免过多的skip

分页不过避免需要先跳过一些数据,这个过程是需要消耗时间的,可以通过一个小技巧避免跳过。

比如,显示列表时,排序为按最后修改时间倒序,每页显示100条,现在要显示第100页。

按照正常的做法,需要跳过99*100条数据,非常大的代价。换一个角度思考,因为数据是有序的,因此第100页的数据的最后修改时间是小于第99页最小的修改时间,查询时加上这个条件,就可以直接取符合条件的前100条即可。

3. 全量导出优化

3.1 去掉不需要的字段

查询时,指定真正有用的字段,这样可以有效减少数据传输量,加快查询效率。

例如:

 	    Query query = new Query();
query.fields().include("_id").include("name").include("hot").include("alias");

3.2 避免使用findAll或者分页查询,改用stream

全量导出有两个误区,一是直接findAll,当数据量过大时,很容易导致服务器OutofMermory,就算没有OOM,也会对服务器造成极大的负载,影响兄弟服务。另外,FindAll一次性加载数据到内存,整个速度也会比较慢,需要等待所有数据进入内存后才能开始处理。

另外一个误区是,分页查询,依次处理。分页查询可以有效减少服务器负担,不失为一种可行的方法。但是就和上面分页说的那样,分页到后面的时候,需要skip掉前面的数据,存在无用功。稍微好一点的做法就是按照之前说的,将skip转换为condtion,这种方式效率OK,但不推荐,存在代码冗余。

            Page<Thing> dataList = entityDao.findAllByPage(kgDataStoreService.getKgCollectionByKgInstance(kg), page);
Map<String, Individual> thingId2Resource = new ConcurrentHashMap<>(); appendThingsToModel(model, concept2OntClass, hot, alias, dataList, thingId2Resource); while (dataList.hasNext()) {
page = PageRequest.of(page.getPageNumber() + 1, page.getPageSize());
dataList = entityDao.findAllByPage(kgDataStoreService.getKgCollectionByKgInstance(kg), page);
appendThingsToModel(model, concept2OntClass, hot, alias, dataList, thingId2Resource);
}

更推荐的做法是,采用mongoTemplate的steam方法,返回CloseableIterator迭代器,读一条数据处理一条数据,实现高效处理:

@Override
public <T> CloseableIterator<T> stream(final Query query, final Class<T> entityType, final String collectionName) {
return doStream(query, entityType, collectionName, entityType);
}

改用方法后,代码可以更简化高效:

  CloseableIterator<Thing> dataList = kgDataStoreService.getSimpleInfoIterator(kg);

            // 实体导入
// Page<Thing> dataList = entityDao.findAllByPage(kgDataStoreService.getKgCollectionByKgInstance(kg), page);
Map<String, Individual> thingId2Resource = new ConcurrentHashMap<>(); appendThingsToModel(model, concept2OntClass, hot, alias, dataList, thingId2Resource);

待续。。。


作者:Jadepeng

出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

mongodb海量数据CRUD优化的更多相关文章

  1. MongoDB的CRUD操作

    1. 前言 在上一篇文章中,我们介绍了MongoDB.现在,我们来看下如何在MongoDB中进行常规的CRUD操作.毕竟,作为一个存储系统,它的基本功能就是对数据进行增删改查操作. MongoDB中的 ...

  2. MongoDB实战性能优化

    1. 性能优化分类 mongodb性能优化分为软件层面和操作系统层面. 软件层面,一般通过修改mongodb软件配置参数来达到,这个需要非常熟悉mongodb里面的各种配置参数: 而操作系统层面,相对 ...

  3. MongoDB简单CRUD场景

    MongoDB简单CRUD命令操作 (1)新建数据库:use 数据库名 (2)显示所有数据库:show dbs; (3)新建集合(两种方式)  隐式创建:在创建集合的同时往集合里面添加数据---db. ...

  4. springboot连接mongodb进行CRUD

    springboot连接mongodb进行CRUD的过程: 在执行以下操作前已安装了mongodb并创建了用户和数据库,使用Robo 3T可成功连接. 1.创建springboot项目,加入以下mav ...

  5. 【翻译】MongoDB指南/CRUD操作(四)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...

  6. 【翻译】MongoDB指南/CRUD操作(三)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Transactions),读隔离.一致性和新近 ...

  7. 【翻译】MongoDB指南/CRUD操作(二)

    [原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(二) 主要内容: 更新文档,删除文档,批量写操作,SQL与MongoDB映射图,读隔离(读关 ...

  8. 【翻译】MongoDB指南/CRUD操作(一)

    [原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(一) 主要内容:CRUD操作简介,插入文档,查询文档. CRUD操作包括创建.读取.更新和删 ...

  9. MongoDB—— 写操作 Core MongoDB Operations (CRUD)

    MongoDB使用BSON文件存储在collection中,本文主要介绍MongoDB中的写操作和优化策略. 主要有三种写操作:        Create        Update        ...

随机推荐

  1. WebLoad 解析服务器返回的JSON格式内容

    服务器返回Json格式的响应内容经常是以 String (txt) 形式返回给客户端.客户端需要把 文本形式的内容还原为Json格式以进一步做处理(如,取得返回内容的一个值作为下个请求的一个输入).这 ...

  2. 前端开发:JQuery(2)& Bootstrap

    JS事件流 事件的概念:HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件. 事件流: ...

  3. 关于android系统启动不同activity默认过渡动画不同的一些认识

    在同一个android设备里,发现不同的app启动时显示的过渡动画是不同的.查看显示不同过渡动画的两个app的源码,其设置的主题都是同一个主题,但是为什么过渡动画效果不同呢?后来发现,activity ...

  4. POJ 2104 K-th Number (可持久化线段树)

    题目大意 给一个长度为n的序列,有m个询问,每次询问一个区间里面第k小的数. 解题分析 静态的区间第k大.复习了一下可持久化线段树. 首先对数值离散化,建一颗权值线段树.按照序列的顺序依次插入,每一个 ...

  5. Java 代理模式和装饰者模式的区别

    装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案:代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式应该为所装饰的对象增强功能:代理模式对代理的 ...

  6. weblogic自带的jdk是在工程的包部署后编译使用

    weblogic自带的jdk是在工程的包部署后编译使用的.当用户把项目打包部署到weblogic上面,运行该项目的java环境jdk就是用的weblogic自带的jdk了,工程中的jdk和编译时的jd ...

  7. 剑指Offer - 开始没做出来 —— 验证后序序列是否正确

    https://www.nowcoder.net/practice/a861533d45854474ac791d90e447bafd?tpId=13&tqId=11176&tPage= ...

  8. Elasticsearch学习系列之单模式下API的增删改查操作

    这里我们通过Elasticsearch的marvel插件实现单模式下API的增删改查操作 索引的初始化操作 创建索引之前可以对索引进行初始化操作,比如先指定shard数量以及replicas的数量 代 ...

  9. C# 复制和克隆认识浅谈

    如有雷同,不胜荣欣.若转载,请注明 在C#中,用HashTable,DataTable等复制和克隆浅谈,以下直接看样例 HashTable ht = null; ht = new HashTable( ...

  10. 【C++/数据结构】单链表的基本操作

    #pragma once #ifndef _CLIST_H_ #define _CLIST_H_ #include <iostream> #include <assert.h> ...