【问题标题】:The speed of mongoimport while using -jsonArray is very slow使用 -jsonArray 时 mongoimport 的速度很慢
【发布时间】:2015-01-11 07:13:00
【问题描述】:

我有一个超过 2500 万行的 15GB 文件,它是这种 json 格式(mongodb 接受用于导入:

[
    {"_id": 1, "value": "\u041c\..."}
    {"_id": 2, "value": "\u041d\..."}
    ...
]

当我尝试使用以下命令将其导入 mongodb 时,我的速度仅为每秒 50 行,这对我来说真的很慢。

mongoimport --db wordbase --collection sentences --type json --file C:\Users\Aleksandar\PycharmProjects\NLPSeminarska\my_file.json -jsonArray

当我尝试使用 python 和 pymongo 将数据插入到集合中时,速度甚至更差。我也尝试增加进程的优先级,但没有任何区别。

接下来我尝试的是同样的事情,但没有使用-jsonArray,虽然我得到了很大的速度提升(~4000/sec),但它说提供的 JSON 的 BSON 表示太大了。

我还尝试将文件拆分为 5 个单独的文件,然后将它们从不同的控制台导入到同一个集合中,但是我将所有这些文件的速度降低到大约 20 个文档/秒。

当我在整个网络上搜索时,我发现人们的文档速度超过 8K/秒,我看不出我做错了什么。

有没有办法加快这件事,或者我应该将整个 json 文件转换为 bson 并以这种方式导入,如果是这样,哪种方法是进行转换和导入的正确方法?

非常感谢。

【问题讨论】:

  • 您确实意识到您的语法首先是错误的,因为它只是--jsonArray 的有效选项。下一点是,由于存在 BSON 限制,因此对可以以这种方式一次“吞食”的数据施加了 16MB 的限制。这里的底线是从您的输入文件中删除包装 [] 括号字符,然后确保在包装文档大括号 {} 之后每一行都以换行符 \n 字符结尾。最终以这种方式处理文件并并行运行多个进程。这是一个 15GB 的文件。你期待什么?毫秒响应?
  • 也很离题。堆栈溢出仅适用于编程主题。这更适合 dba.stackexchange.com 以及您应该首先发布的位置。
  • @NeilLunn ,非常感谢您的回复,删除 [] 括号并且不使用 --jsonArray 使导入以每秒大约 8500 个文档的速度进行。感谢您将我指向正确的网站,祝您有美好的一天。
  • @buncis 考虑使用这种方法stackoverflow.com/questions/49808581/…

标签: json performance mongodb import bson


【解决方案1】:

我对 160Gb 转储文件有完全相同的问题。我花了两天时间用-jsonArray 加载原始文件的 3%,而这些更改花了 15 分钟。

首先,删除开头的[ 和结尾的] 字符:

sed 's/^\[//; s/\]$/' -i filename.json

然后在不带-jsonArray 选项的情况下导入:

mongoimport --db "dbname" --collection "collectionname" --file filename.json

如果文件很大,sed 将需要很长时间,并且可能会遇到存储问题。你可以改用这个 C 程序(不是我写的,所有的荣耀归于@guillermobox):

int main(int argc, char *argv[])
{
    FILE * f;
    const size_t buffersize = 2048;
    size_t length, filesize, position;
    char buffer[buffersize + 1];

    if (argc < 2) {
        fprintf(stderr, "Please provide file to mongofix!\n");
        exit(EXIT_FAILURE);
    };

    f = fopen(argv[1], "r+");

    /* get the full filesize */
    fseek(f, 0, SEEK_END);
    filesize = ftell(f);

    /* Ignore the first character */
    fseek(f, 1, SEEK_SET);

    while (1) {
        /* read chunks of buffersize size */
        length = fread(buffer, 1, buffersize, f);
        position = ftell(f);

        /* write the same chunk, one character before */
        fseek(f, position - length - 1, SEEK_SET);
        fwrite(buffer, 1, length, f);

        /* return to the reading position */
        fseek(f, position, SEEK_SET);

        /* we have finished when not all the buffer is read */
        if (length != buffersize)
            break;
    }

    /* truncate the file, with two less characters */
    ftruncate(fileno(f), filesize - 2);

    fclose(f);

    return 0;
};

P.S.:我无权建议迁移此问题,但我认为这可能会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2019-04-20
    • 2018-12-08
    • 1970-01-01
    • 2016-05-19
    • 2016-12-18
    相关资源
    最近更新 更多