我们数据库里有4000W数据,现在想将里面的数据规整一下放到另一张表里(数据类型规整),于是写 了java个程序进行类型转换,然后一条条的查出来处理后再插入到mongo里,在此之前也有过这样的经历,但是并不是一次性存入这样大量的数据,没有瓶颈存在,后来发现当我总数100W左右,整个程序就会假死状态,不能查询也不能插入,刚开始我认为是mongo性能瓶颈了,于是去查看服务器,发现cpu,内存,连接数都很正常,一点都不高,就是不执行;监听Java堆栈也未发现异常,很奇怪,也没找到原因;再后来分析因为我是insertOne,mongo在插入数据的时候会有一次数据验证,比如ObjectId是否重复等,也许是我这种连续插入让mongo这个验证卡住了,,暂时锁住了表。。当我退出程序,,锁就自动关了(个人)
mongo查询:http://www.360doc.com/content/15/1230/15/20874412_524191840.shtml 说了下mongo查询:
mongo的查询,使用cursur查询的时候,如果没有设置batch size这个参数,那么mongo默认会返回101条数据,等这101条数据读取完了,也就是想读取第102条的时候,那么驱动会再去数据库读取下一批数据,这批数据不是用条数来限定的,而是最大限制为4m,放入内存,等该数据读完了再去取下一次4M; mongo本身为异步读写;
但我觉得并不是这样,因为我每一次查询的时候都driver都会有日志输出(mongo Java driver)自带的,每一次都会去请求数据库,我还是认为是我的链接太频繁让mongo连接池卡住了(读写)
于是我手动设置了batchSize后,发现读取的时候不会每一次都有日志输入了,说明它真的是每一次去拿50000条数据,一次链接申请;
再使用insertMany,却发现每次最大写入为1000条,这个速度已经赶上我开50个线程用最开始的单条读写了(现在为单线程);
public static void insert(Document query){ FindIterable<Document> findIterable = mv150.collection.find(query).batchSize(50000);//batchSize 设置每次取出数据量 MongoCursor<Document> cursor = findIterable.iterator(); InsertManyOptions options = new InsertManyOptions();//不开启验证/ 效率更快 options.ordered(false); //ExecutorService executorService = Executors.newFixedThreadPool(100); 本来最开始想用多线程 final List<Document> list = new ArrayList<>(); while(cursor.hasNext()){ final Document d = cursor.next(); list.add(resetBDLPType(d)); if(list.size()==50000){ /* executorService.submit(new Runnable() { @Override public void run() { mvbasic.collection.insertMany(list); } });*/ mvbasic.collection.insertMany(list,options); list.clear(); } } cursor.close(); }
InsertManyOptions options = new InsertManyOptions();//不开启验证/ 效率更快 options.ordered(false); final List<Document> list = new ArrayList<>(); while(cursor.hasNext()){ final Document d = cursor.next(); list.add(resetBDLPType(d)); if(list.size()==50000){ mvbasic.collection.insertMany(list,options); list.clear(); } }