国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何高效地遍歷 MongoDB 超大集合?

Batkid / 747人閱讀

摘要:執(zhí)行測試代碼兩種不同遍歷方法的代碼分別位于和。參考如何使用對一個(gè)萬的的表進(jìn)行遍歷操作關(guān)于專注于微信小程序微信小游戲支付寶小程序和線上應(yīng)用實(shí)時(shí)監(jiān)控。自從年雙十一正式上線,累計(jì)處理了億錯(cuò)誤事件,付費(fèi)客戶有金山軟件百姓網(wǎng)等眾多品牌企業(yè)。

GitHub 倉庫:Fundebug/loop-mongodb-big-collection

本文使用的編程語言是 Node.js,連接 MongoDB 的模塊用的是mongoose。但是,本文介紹的方法適用于其他編程語言及其對應(yīng)的 MongoDB 模塊。

錯(cuò)誤方法:find()

也許,在遍歷 MongoDB 集合時(shí),我們會(huì)這樣寫:

const Promise = require("bluebird");

function findAllMembers() {
    return Member.find();
}

async function test() {
    const members = await findAllMembers();
    let N = 0;
    await Promise.mapSeries(members, member => {
        N++;
        console.log(`name of the ${N}th member: ${member.name}`);
    });
    console.log(`loop all ${N} members success`);
}

test();

注意,我們使用的是 Bluebird 的mapSeries而非map,members 數(shù)組中的元素是一個(gè)一個(gè)處理的。這樣就夠了嗎?

當(dāng) Member 集合中的 document 不多時(shí),比如只有 1000 個(gè)時(shí),那確實(shí)沒有問題。但是當(dāng) Member 集合中有 1000 萬個(gè) document 時(shí),會(huì)發(fā)生什么呢?如下:

<--- Last few GCs --->
rt of marking 1770 ms) (average mu = 0.168, current mu = 0.025) finalize [5887:0x43127d0]    33672 ms: Mark-sweep 1398.3 (1425.2) -> 1398.0 (1425.7) MB, 1772.0 / 0.0 ms  (+ 0.1 ms in 12 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1775 ms) (average mu = 0.088, current mu = 0.002) finalize [5887:0x43127d0]    35172 ms: Mark-sweep 1398.5 (1425.7) -> 1398.4 (1428.7) MB, 1496.7 / 0.0 ms  (average mu = 0.049, current mu = 0.002) allocation failure scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x8c02c0 node::Abort() [node]
 2: 0x8c030c  [node]
 3: 0xad15de v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xad1814 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xebe752  [node]
 6: 0xebe858 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [node]
 7: 0xeca982 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
 8: 0xecb2b4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 9: 0xecba8a v8::internal::Heap::FinalizeIncrementalMarkingIfComplete(v8::internal::GarbageCollectionReason) [node]
10: 0xecf1b7 v8::internal::IncrementalMarkingJob::Task::RunInternal() [node]
11: 0xbc1796 v8::internal::CancelableTask::Run() [node]
12: 0x935018 node::PerIsolatePlatformData::FlushForegroundTasksInternal() [node]
13: 0x9fccff  [node]
14: 0xa0dbd8  [node]
15: 0x9fd63b uv_run [node]
16: 0x8ca6c5 node::Start(v8::Isolate*, node::IsolateData*, int, char const* const*, int, char const* const*) [node]
17: 0x8c945f node::Start(int, char**) [node]
18: 0x7f84b6263f45 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
19: 0x885c55  [node]
Aborted (core dumped)

可知,內(nèi)存不足了。

打印find()返回的 members 數(shù)組可知,集合中所有元素都返回了,哪個(gè)數(shù)組放得下 1000 萬個(gè) Object?

正確方法:find().cursor()與 eachAsync()

將整個(gè)集合 find()全部返回,這種操作應(yīng)該避免,正確的方法應(yīng)該是這樣的:

function findAllMembersCursor() {
    return Member.find().cursor();
}

async function test() {
    const membersCursor = await findAllMembersCursor();
    let N = 0;
    await membersCursor.eachAsync(member => {
        N++;
        console.log(`name of the ${N}th member: ${member.name}`);
    });
    console.log(`loop all ${N} members success`);
}

test();

使用cursor()方法返回 QueryCursor,然后再使用eachAsync()就可以遍歷整個(gè)集合了,而且不用擔(dān)心內(nèi)存不夠。

QueryCursor是什么呢?不妨看一下 mongoose 文檔:

A QueryCursor is a concurrency primitive for processing query results one document at a time. A QueryCursor fulfills the Node.js streams3 API, in addition to several other mechanisms for loading documents from MongoDB one at a time.

總之,QueryCursor 可以每次從 MongoDB 中取一個(gè) document,這樣顯然極大地減少了內(nèi)存使用。

如何測試?

這篇博客介紹的內(nèi)容很簡單,但是也很容易被忽視。如果大家測試一下,印象會(huì)更加深刻一些。

測試代碼很簡單,大家可以查看Fundebug/loop-mongodb-big-collection。

我的測試環(huán)境是這樣的:

ubuntu 14.04

mongodb 3.2

nodejs 10.9.0

1. 使用 Docker 運(yùn)行 MongoDB

sudo docker run --net=host -d --name mongodb daocloud.io/library/mongo:3.2

2. 使用mgodatagen生成測試數(shù)據(jù)

使用 mgodatagen,1000 萬個(gè) document 可以在 1 分多鐘生成!

下載 mgodatagen:https://github.com/feliixx/mgodatagen/releases/download/0.7.3/mgodatagen_linux_x86_64.tar.gz

解壓之后,復(fù)制到/usr/local/bin 目錄即可:

sudo mv mgodatagen /usr/local/bin

mgodatagen 的配置文件mgodatagen-config.json如下:

[
    {
        "database": "test",
        "collection": "members",
        "count": 10000000,
        "content": {
            "name": {
                "type": "string",
                "minLength": 2,
                "maxLength": 8
            },
            "city": {
                "type": "string",
                "minLength": 2,
                "maxLength": 8
            },
            "country": {
                "type": "string",
                "minLength": 2,
                "maxLength": 8
            },
            "company": {
                "type": "string",
                "minLength": 2,
                "maxLength": 8
            },
            "email": {
                "type": "string",
                "minLength": 2,
                "maxLength": 8
            }
        }
    }
]

執(zhí)行mgodatagen -f mgodatagen-config.json命令,即可生成 10000 萬測試數(shù)據(jù)。

mgodatagen -f mgodatagen-config.json
Connecting to mongodb://127.0.0.1:27017
MongoDB server version 3.2.13

collection members: done            [====================================================================] 100%

+------------+----------+-----------------+----------------+
| COLLECTION |  COUNT   | AVG OBJECT SIZE |    INDEXES     |
+------------+----------+-----------------+----------------+
| members    | 10000000 |             108 | _id_  95368 kB |
+------------+----------+-----------------+----------------+

run finished in 1m12.82s

查看 MongoDB,可知新生成的數(shù)據(jù)有 0.69GB,其實(shí)很小,但是使用 find()方法遍歷會(huì)報(bào)錯(cuò)。

show dbs
local  0.000GB
test   0.690GB

3. 執(zhí)行測試代碼

兩種不同遍歷方法的代碼分別位于test1.js和test2.js。

參考

如何使用 mongoose 對一個(gè) 100 萬+的 mongodb 的表進(jìn)行遍歷操作

Cursors in Mongoose 4.5

關(guān)于Fundebug

Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了10億+錯(cuò)誤事件,付費(fèi)客戶有Google、360、金山軟件、百姓網(wǎng)等眾多品牌企業(yè)。歡迎大家免費(fèi)試用!

版權(quán)聲明

轉(zhuǎn)載時(shí)請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2019/03/21/how-to-visit-all-documents-in-a-big-collection-of-mongodb/

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/19482.html

相關(guān)文章

  • 如何高效遍歷 MongoDB 超大集合

    摘要:執(zhí)行測試代碼兩種不同遍歷方法的代碼分別位于和。參考如何使用對一個(gè)萬的的表進(jìn)行遍歷操作關(guān)于專注于微信小程序微信小游戲支付寶小程序和線上應(yīng)用實(shí)時(shí)監(jiān)控。自從年雙十一正式上線,累計(jì)處理了億錯(cuò)誤事件,付費(fèi)客戶有金山軟件百姓網(wǎng)等眾多品牌企業(yè)。 GitHub 倉庫:Fundebug/loop-mongodb-big-collection showImg(https://segmentfault.c...

    王晗 評(píng)論0 收藏0
  • MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對象和數(shù)組、索引基數(shù)

    摘要:操作符如何使用索引有一些查詢完全無法使用索引,也有一些查詢能夠比其他查詢更高效地使用索引。有時(shí)能夠使用索引,但是通常它并不知道要如何使用索引。索引對象和數(shù)組允許深入文檔內(nèi)部,對嵌套字段和數(shù)組建立索引。 上一篇文章:MongoDB指南---10、索引、復(fù)合索引 簡介下一篇文章:MongoDB指南---12、使用explain()和hint()、何時(shí)不應(yīng)該使用索引 1、使用復(fù)合索引 在多...

    saucxs 評(píng)論0 收藏0
  • MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對象和數(shù)組、索引基數(shù)

    摘要:操作符如何使用索引有一些查詢完全無法使用索引,也有一些查詢能夠比其他查詢更高效地使用索引。有時(shí)能夠使用索引,但是通常它并不知道要如何使用索引。索引對象和數(shù)組允許深入文檔內(nèi)部,對嵌套字段和數(shù)組建立索引。 上一篇文章:MongoDB指南---10、索引、復(fù)合索引 簡介下一篇文章:MongoDB指南---12、使用explain()和hint()、何時(shí)不應(yīng)該使用索引 1、使用復(fù)合索引 在多...

    tomlingtm 評(píng)論0 收藏0
  • MongoDB指南---10、索引、復(fù)合索引 簡介

    摘要:可以通過來強(qiáng)制使用某個(gè)特定的索引,再次執(zhí)行這個(gè)查詢,但是這次使用,作為索引。 上一篇文章:MongoDB指南---9、游標(biāo)與數(shù)據(jù)庫命令下一篇文章:MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對象和數(shù)組、索引基數(shù) 本章介紹MongoDB的索引,索引可以用來優(yōu)化查詢,而且在某些特定類型的查詢中,索引是必不可少的。 什么是索引?為什么要用索引? 如何選擇需要建立...

    enrecul101 評(píng)論0 收藏0
  • MongoDB指南---10、索引、復(fù)合索引 簡介

    摘要:可以通過來強(qiáng)制使用某個(gè)特定的索引,再次執(zhí)行這個(gè)查詢,但是這次使用,作為索引。 上一篇文章:MongoDB指南---9、游標(biāo)與數(shù)據(jù)庫命令下一篇文章:MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對象和數(shù)組、索引基數(shù) 本章介紹MongoDB的索引,索引可以用來優(yōu)化查詢,而且在某些特定類型的查詢中,索引是必不可少的。 什么是索引?為什么要用索引? 如何選擇需要建立...

    leiyi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

Batkid

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<