亿级别记录的mongodb分页查询java代码实现
1.准备环境
1.1 mongodb下载
1.2 mongodb启动
C:\mongodb\bin\mongod --dbpath D:\mongodb\data
1.3 可视化mongo工具Robo 3T下载
2.准备数据
- <dependency>
- <groupId>org.mongodb</groupId>
- <artifactId>mongo-java-driver</artifactId>
- <version>3.6.1</version>
- </dependency>
java代码执行
- public static void main(String[] args) {
- try {
- /**** Connect to MongoDB ****/
- // Since 2.10.0, uses MongoClient
- MongoClient mongo = new MongoClient("localhost", 27017);
- /**** Get database ****/
- // if database doesn't exists, MongoDB will create it for you
- DB db = mongo.getDB("www");
- /**** Get collection / table from 'testdb' ****/
- // if collection doesn't exists, MongoDB will create it for you
- DBCollection table = db.getCollection("person");
- /**** Insert ****/
- // create a document to store key and value
- BasicDBObject document=null;
- for(int i=0;i<100000000;i++) {
- document = new BasicDBObject();
- document.put("name", "mkyong"+i);
- document.put("age", 30);
- document.put("sex", "f");
- table.insert(document);
- }
- /**** Done ****/
- System.out.println("Done");
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (MongoException e) {
- e.printStackTrace();
- }
- }
3.分页查询
传统的limit方式当数据量较大时查询缓慢,不太适用。考虑别的方式,参考了logstash-input-mongodb的思路:
- public
- def get_cursor_for_collection(mongodb, mongo_collection_name, last_id_object, batch_size)
- collection = mongodb.collection(mongo_collection_name)
- # Need to make this sort by date in object id then get the first of the series
- # db.events_20150320.find().limit(1).sort({ts:1})
- return collection.find({:_id => {:$gt => last_id_object}}).limit(batch_size)
- end
- collection_name = collection[:name]
- @logger.debug("collection_data is: #{@collection_data}")
- last_id = @collection_data[index][:last_id]
- #@logger.debug("last_id is #{last_id}", :index => index, :collection => collection_name)
- # get batch of events starting at the last_place if it is set
- last_id_object = last_id
- if since_type == 'id'
- last_id_object = BSON::ObjectId(last_id)
- elsif since_type == 'time'
- if last_id != ''
- last_id_object = Time.at(last_id)
- end
- end
- cursor = get_cursor_for_collection(@mongodb, collection_name, last_id_object, batch_size)
使用java实现
- import java.net.UnknownHostException;
- import java.util.List;
- import org.bson.types.ObjectId;
- import com.mongodb.BasicDBObject;
- import com.mongodb.DB;
- import com.mongodb.DBCollection;
- import com.mongodb.DBCursor;
- import com.mongodb.DBObject;
- import com.mongodb.MongoClient;
- import com.mongodb.MongoException;
- public class Test {
- public static void main(String[] args) {
- int pageSize=50000;
- try {
- /**** Connect to MongoDB ****/
- // Since 2.10.0, uses MongoClient
- MongoClient mongo = new MongoClient("localhost", 27017);
- /**** Get database ****/
- // if database doesn't exists, MongoDB will create it for you
- DB db = mongo.getDB("www");
- /**** Get collection / table from 'testdb' ****/
- // if collection doesn't exists, MongoDB will create it for you
- DBCollection table = db.getCollection("person");
- DBCursor dbObjects;
- Long cnt=table.count();
- //System.out.println(table.getStats());
- Long page=getPageSize(cnt,pageSize);
- ObjectId lastIdObject=new ObjectId("5bda8f66ef2ed979bab041aa");
- for(Long i=0L;i<page;i++) {
- Long start=System.currentTimeMillis();
- dbObjects=getCursorForCollection(table, lastIdObject, pageSize);
- System.out.println("第"+(i+1)+"次查询,耗时:"+(System.currentTimeMillis()-start)/1000+"秒");
- List<DBObject> objs=dbObjects.toArray();
- lastIdObject=(ObjectId) objs.get(objs.size()-1).get("_id");
- }
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (MongoException e) {
- e.printStackTrace();
- }
- }
- public static DBCursor getCursorForCollection(DBCollection collection,ObjectId lastIdObject,int pageSize) {
- DBCursor dbObjects=null;
- if(lastIdObject==null) {
- lastIdObject=(ObjectId) collection.findOne().get("_id"); //TODO 排序sort取第一个,否则可能丢失数据
- }
- BasicDBObject query=new BasicDBObject();
- query.append("_id",new BasicDBObject("$gt",lastIdObject));
- BasicDBObject sort=new BasicDBObject();
- sort.append("_id",1);
- dbObjects=collection.find(query).limit(pageSize).sort(sort);
- return dbObjects;
- }
- public static Long getPageSize(Long cnt,int pageSize) {
- return cnt%pageSize==0?cnt/pageSize:cnt/pageSize+1;
- }
- }
4.一些经验教训
1. 不小心漏打了一个$符号,导致查询不到数据,浪费了一些时间去查找原因
- query.append("_id",new BasicDBObject("$gt",lastIdObject));
2.创建索引
创建普通的单列索引:db.collection.ensureIndex({field:1/-1}); 1是升续 -1是降续
实例:db.articles.ensureIndex({title:1}) //注意 field 不要加""双引号,否则创建不成功
查看当前索引状态: db.collection.getIndexes();
实例:
db.articles.getIndexes();
删除单个索引db.collection.dropIndex({filed:1/-1});
3.执行计划
db.student.find({"name":"dd1"}).explain()
参考文献:
【1】https://github.com/phutchins/logstash-input-mongodb/blob/master/lib/logstash/inputs/mongodb.rb
【2】https://www.cnblogs.com/yxlblogs/p/4930308.html
【3】https://docs.mongodb.com/manual/reference/method/db.collection.ensureIndex/
亿级别记录的mongodb分页查询java代码实现的更多相关文章
- 亿级别记录的mongodb批量导入Es的java代码完整实现
针对mongodb亿级别或者十亿级别的模糊查询,效率不高,解决方式是使用Es查询,这样就需要把数据导入的ES中 完整的代码实现如下所示:(仅供参考) import java.io.IOExceptio ...
- MongoDB分页的Java实现和分页需求的思考
前言 传统关系数据库中都提供了基于row number的分页功能,切换MongoDB后,想要实现分页,则需要修改一下思路. 传统分页思路 假设一页大小为10条.则 //page 1 1-10 //pa ...
- Mybatis包分页查询java公共类
Mybatis包分页查询java公共类 分页----对于数据量非常大的查询中.是不可缺少的. mybatis底层的分页sql语句因为须要我们自己去手动写.而实现分页显示的时候我们须要依据分页查询条 ...
- 分页查询关键代码 多条件查询关键代码 删除选中商品关键代码 修改要先回显再修改 修改要先回显再修改 同一业务集中使用同一servlet的方法
分页查询关键代码: 通过servlet转发回来的各种信息进行分页的设计(转发回的信息有 分页查询的List集合 查询的页码 查询的条数 查询的数据库总条数 查询的总页码) 从开始时循环10次出现十个数 ...
- MongoDB 分页查询的方法及性能
最近有点忙,本来有好多东西可以总结,Redis系列其实还应该有四.五.六...不过<Redis in Action>还没读完,等读完再来总结,不然太水,对不起读者. 自从上次Redis之后 ...
- C#MongoDB 分页查询的方法及性能
传统的SQL分页 传统的sql分页,所有的方案几乎是绕不开row_number的,对于需要各种排序,复杂查询的场景,row_number就是杀手锏.另外,针对现在的web很流行的poll/push加载 ...
- Spring Data MongoDB 分页查询
在上篇文章 Spring Data MongoDB 环境搭建 基础上进行分页查询 定义公用分页参数类,实现 Pageable 接口 import java.io.Serializable; impor ...
- (记录)mysql分页查询,参数化过程的坑
在最近的工作中,由于历史遗留,一个分页查询没有参数化,被查出来有sql注入危险,所以对这个查询进行了参数化修改. 一看不知道,看了吓一跳,可能由于种种原因,分页查询sql是在存储过程中拼接出来的,wh ...
- 使用mybatis实现分页查询示例代码分析
*******************************************分页查询开始*************************************************** ...
随机推荐
- 关于如何参与到开源项目中《How To Succeed In Open Source ( In Ways You Haven't Considered Yet )》
转自:http://gaslight.co/blog/how-to-succeed-in-open-source-in-ways-you-havent-considered-yet It’s Easy ...
- 使用像素单位设置 EXCEL 列宽或行高
在导出 Excel 的时候, 经常要需要给列设置宽度或给行设置高度, 在使用 NPOI 或 EppPlus 等组件进行操作的时候, 列宽和行高的单位都不是像素, 好像是英寸,具体是啥也说不清. 平常在 ...
- ActiveX 控件重绘无效问题,用CClientDC 而不是CPaintDC
ActiveX 控件重绘子控件时,用Invalid()会出现无效的情况即不会更新界面. OnPaint 方法里,是用的 CPaintDC,经测试无效,后换CClientDC,发现可以,百度查他们的区别 ...
- WPF 降低.net framework到4.0
1. 问题背景 由于xp系统上面最高只能安装.net framework 4.0,所以公司项目需要将原来项目的.net framework版本降低到4.0,具体的降版本很简单,只要把项目属性中的目标框 ...
- 【OCP|052】OCP最新题库解析系列-3
3.Which structure can span multiple data files?❑ A) a permanent tablespace❑ B) a bigfile tablespace❑ ...
- Java 设计模式——单例模式
Java有很多的设计模式,但是让我们一个个分析出来,可能就一脸蒙逼了,今天就和大家一块来分析一下Java中的一些常用的设计模式.今天先分析单例模式 单例模式的好处 举个例子:有一个类,里面有若干个公共 ...
- css 实现关闭按钮 X
.close::before { content: "\2716";} 然后就显示出来了 这里有个更直接的例子 <!DOCTYPE html> <html lan ...
- php脚本cli 模式运行
参考文章 http://rapheal.sinaapp.com/2013/11/20/php_zend_hello_world/ http://www.douban.com/note/33788568 ...
- 题目1001:A+B for Matrices(简单循环)
问题来源 http://ac.jobdu.com/problem.php?pid=1001 问题描述 给你两个形式相同的矩阵,对应位置相加得到新矩阵,计算里面全为0的行数和列数. 问题分析 这里其实只 ...
- canvas+js绘制序列帧动画+面向对象
效果: 素材: 源码:(一般的绘制方式) <!DOCTYPE html> <html lang="en"> <head> <meta ch ...