如何遍歷資料量億級別Mongo庫
場景介紹
在使用Mongo這種非關係型資料庫過程中,往往儲存了海量的資料,這些資料的資料結構非常鬆散,資料型別比較複雜。對於從海量資料中提取或分析資料,需要遍歷Mongo庫的情況經常出現,這裡介紹兩種比較有效的方法,均在億級別的生產庫中,多次使用過。
方法一:利用時間戳
在儲存的資料中,對時間戳欄位,建立索引,如下方資料時間戳欄位為update_time
{
"_id" : "6214627359000222889",
"_class" : "com.alibaba.fastjson.JSONObject",
"update_time" : ISODate("2018-07-05T14:26:42.018Z"),
"idcard" : "342522199406220025",
"gender" : "女",
"age" : "24",
"name" : "曹××"
}
這種方法遍歷,我們需要一個起點時間,和結束時間,然後按照這個時間段進行掃庫,億級別的資料,不可能全部取出,可每次取出一定數量,比如1K條,排序後根據最後一條的時間戳,與結束時間根據你是逆序遍歷,還是順序遍歷進行判斷,如此迴圈,Demo如下。
//順序遍歷,所以結束時間為當前時間
Date endDate = new Date();
//開始時間
Date startDate = minDate;
while(startDate < endDate ){
Query query = new Query();
query.addCriteria(Criteria.where("update_time").gt(startDate));
//這裡可以自己寫一些查詢條件
//對時間的排序
query.with(new Sort(new Sort.Order(Sort.Direction.ASC,"update_time")));
query.limit(1000);
List<JSONObject> list = mongoTemplate.find(query,JSONObject.class,"collectionName");
//將每次取出的最後時間,賦值,然後跟結束時間比較
startDate = list.get(list.size()-1).getDate("update_time");
//處理資料
for(JSONObject json:list){
}
}
要點
- 必須擁有時間戳欄位,且必須建立索引;
- 需要查出最大時間和最小時間;
這兩個點,也是這種方法的缺點,有些庫中時間戳欄位沒有建立索引,或者庫中的有些資料也沒有時間戳,或者時間戳錯誤,這些情況就沒法使用這種方法掃庫遍歷。可以使用第二種方法。
方法二:Mongo 遊標的使用(推薦)
Mongo的遊標無論是功能還是使用的便捷上,都比MySQL強上許多,在MySQL中使用遊標還需要PL/SQL程式設計,比較麻煩而Mongo卻不用。Mongo中的遊標可以實現根據條件查詢和指定使用投影運算子返回匹配文件中的所有欄位。並返回到匹配文件的遊標,可以隨意修改查詢限制、跳躍、和排序順序的功能。Demo如下
BasicDBObject query = new BasicDBObject();
//查詢條件,比如年齡,性別之內的,比如篩選,性別男性,年齡30歲以下,20歲以上。
query.put("gender", "男");
query.put("age",new BasicDBObject().append("$gte",20).append("$lt",30));
DBCursor cursor = mongoTemplate.getCollection("collectionName").find(query);
//防止超時
cursor.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
while (cursor.hasNext()) {
//資料取出
DBObject reuslt = cursor.next();
}
使用cursor來進行遍歷,cursor會每次取出一定的資料量,也已經對庫中的資料進行了排序,在進行資料處理同時cursor一直都在進行遍歷的操作,極大的增快了效率。
優點
相較於第一種根據時間戳來進行遍歷的方法,使用遊標的會比較方便,不用建立索引,不用考慮分頁的操作。
備註
無論是哪種方法,在遍歷跑批過程中最好記錄一下當前遍歷的位置,一旦程式出現異常中斷,避免從頭跑批。比如,使用時間戳來遍歷,記錄一下當前遍歷到了資料的時間,程式異常中斷時根據記錄的時間來重新遍歷,使用遊標的時候,定義一個計數器,異常中斷時,重啟後,可以用skip從中斷點開始。
相關文章
- 【DataMagic】如何在萬億級別規模的資料量上使用SparkSpark
- 上億級別資料庫查詢資料庫
- 資料遍歷
- 如何遍歷 HashMap,遍歷HashMap 的 5 種最佳方式HashMap
- 如何遍歷HashMap集合?HashMap
- Python字典的遍歷,包括key遍歷/value遍歷/item遍歷/Python
- python對常見資料型別的遍歷Python資料型別
- indexedDB 遍歷資料Index
- MSSQL遍歷資料庫根據列值查詢資料SQL資料庫
- 資料量與資料庫選型資料庫
- DBA福音 | 如何無視資料量快速搭建測試資料庫資料庫
- 利用 python 遍歷多級資料夾處理不同檔案Python
- 批次影像識別的快速遍歷技巧
- 【mongo】mongo 欄位型別互轉Go型別
- Serverless 解惑——函式計算如何訪問 Mongo 資料庫Server函式Go資料庫
- js的map遍歷和array遍歷JS
- mongo資料庫單節點搭建Go資料庫
- TDengine 如何助力鋼鐵行業處理日均億級的資料量?來看幾個真實案例行業
- js資料處理——遍歷JS
- 遠端, 資料夾遍歷
- Shell:如何遍歷包含空格的文字
- 資料庫隔離級別資料庫
- 如何將 winston log 庫記錄的日誌寫入 mongo DB 資料庫Go資料庫
- 遍歷 FlowDocument
- Linuxshell遍歷Linux
- jQuery 遍歷jQuery
- 查詢資料庫的資料量的大小資料庫
- 【Mongo】mongorestore恢復資料特別慢GoREST
- 使用mongo-express管理mongodb資料庫ExpressMongoDB資料庫
- jquery遍歷得到的 Map 資料,jQuery
- Oracle 41億資料量表建立索引記錄Oracle索引
- 說說在 Python 中如何遍歷字典Python
- java陣列如何遍歷全部的元素Java陣列
- 喂,不是吧!一遍弄懂樹、圖的遍歷操作------入門級
- 2.6.9 指定資料庫相容級別資料庫
- jQuery的遍歷結構設計之遍歷同胞jQuery
- jQuery的遍歷結構設計之遍歷祖先jQuery
- php手冊 php陣列的遍歷有哪幾種方式?php陣列如何遍歷?PHP陣列