2015-01-11 2 views
4

У меня есть 15ГБ файл с более чем 25 Milion строк, который находится в этом формате JSON (который принимается MongoDB для импорта:Скорость mongoimport при использовании -jsonArray очень медленно

[ 
    {"_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 

Когда я попытался вставить данные в коллекцию с помощью питона с PyMongo скорость была еще хуже. Я также попытался увеличить приоритет процесса, но он d Не имеет значения.

Следующее, что я пробовал, это одно и то же, но без использования -jsonArray, и хотя я получил большое увеличение скорости (~ 4000/сек), он сказал, что представление BSON поставляемого JSON слишком велико.

Я также попытался разбить файл на 5 отдельных файлов и импортировать их из отдельных консолей в один и тот же набор, но я получаю снижение скорости всех из них до 20 документов в секунду.

Когда я искал по сети, я видел, что люди имели скорость более 8 тыс. Документов в секунду, и я не вижу, что я делаю неправильно.

Есть ли способ ускорить это, или мне нужно преобразовать весь json-файл в bson и импортировать его таким образом, и если да, то какой правильный способ сделать и преобразование и импорт?

Огромное спасибо.

+2

Вы понимаете, что ваш синтаксис в первую очередь ошибочен, поскольку это только допустимый параметр с '--jsonArray'. Следующий момент состоит в том, что существует ограничение на 16 МБ, наложенное на данные, которые могут быть «раздроблены» одновременно таким образом, поскольку существует лимит BSON. Нижняя строка здесь заключается в том, чтобы удалить обернутые символы '[]' bracket из вашего входного файла, а затем убедитесь, что каждая строка завершена символом newline '\ n' после того, как документ для упаковки скобок' {} '.. В конечном итоге разбить файл обрабатывается таким образом и параллельно запускает несколько процессов. Это 15-гигабайтный файл. Чего ты ожидал? Миллисекундный ответ? –

+0

Также очень не по теме. Переполнение стека относится только к темам программирования. Это лучше подходит для [dba.stackexchange.com] (http://dba.stackexchange.com) и где вы должны были разместить это в первую очередь. –

+1

@NeilLunn, большое спасибо за ваш ответ, удалив скобки [] и не используя --jsonArray, сделали импорт примерно с 8500 документами в секунду. И спасибо за то, что указали мне на правильный сайт, хорошо провели день. – Aleksandar

ответ

2

У меня такая же проблема с файлом дампа 160 ГБ. Мне потребовалось два дня, чтобы загрузить 3% исходного файла -jsonArray и 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; 
}; 

PS: Я не в силах предложить миграцию этого вопроса, но я думаю, что это может быть полезным ,

Смежные вопросы