Как эффективно обрабатывать миллионы записей и сохранять их в базе данных? - PullRequest
0 голосов
/ 02 мая 2018

Я использую Django с Python 2.7. У меня лист Excel с миллионами строк. Я должен манипулировать данными строк и сохранять обратно в базу данных (postgresql). Я хочу сделать это эффективно. Ниже приведены подходы, о которых я думаю:

1.) Ставит в очередь все строки (данные) в очереди (предпочтительно RabbitMQ) и извлекает сразу из 100 записей. и выполнит и сохранит его в базе данных.

2.) Думать об использовании потока в фоновом режиме, который будет управлять 100 строками для каждого потока и сохранит результат в базе данных. я не убедитесь, сколько соединений с базой данных будет открыто в этом сценарии.

Можете ли вы предложить мне эффективный способ достижения этого. это будет действительно очень полезно.

1 Ответ

0 голосов
/ 02 мая 2018

Вы можете создать дополнительные потоки в вашем обработчике запросов Django, и каждый из них будет иметь свое собственное соединение с базой данных. Но тогда возникает вопрос, насколько улучшится производительность вставки вашей базы данных с несколькими операциями?

Например, если ваша таблица имеет уникальные ограничения, это может замедлить одновременную запись. Тогда вы можете обнаружить, что ваше реальное узкое место - пропускная способность диска и что вы не сможете масштабировать, добавляя соединения.

Так что вы можете захотеть написать какой-нибудь быстрый и грязный тестовый код, чтобы попробовать многопоточные параллельные записи в соответствующую таблицу / базу данных, прежде чем вы зайдете слишком далеко с оптимизацией.

Насколько вы эффективно распределяете данные между потоками, зависит от формата ввода.

Если вы имеете дело с файлом формата Microsoft, таким как .xls, тогда вы захотите использовать библиотеку для анализа этого ... Я успешно использовал xlrd. Но это приводит к тому, что все данные вашей электронной таблицы хранятся в памяти одновременно ... вы не можете прочитать их по одной строке за раз. Но при условии, что вы можете справиться с использованием памяти, это упростит процесс создания потоков: как только вы прочитаете все данные в память, запустите несколько потоков записи, сообщив каждому диапазон номеров строк, за которые он отвечает. Затем основной поток запросов может просто присоединиться к потокам записи, а когда все они будут завершены, он может вернуть Ответ пользователю. Однако имейте в виду, что если ваш запрос занимает слишком много времени, время ожидания браузера истечет. Это другая проблема, и для этого я предлагаю посмотреть другой ответ, который я написал на днях о том, как использовать StreamingHttpResponse:

Правильный способ отсрочки загрузки файла в Django

Теперь, если ваш входной формат - что-то вроде .csv файла, который вы можете читать по одной записи за раз, возможный способ справиться с этим - создать очередь в памяти с использованием класса python Queue ( https://docs.python.org/2/library/queue.html). Запустите ваши потоки записи и попросите их прослушивать в очереди записи для записи в базу данных, затем ваш основной поток считывает из файла .csv по одной записи за раз и помещает эти записи в очередь.

Все эти предложения направлены на обработку ваших данных прямо в запросе Django. Но если вы не хотите этого делать, вы можете разгрузить обработку различными способами. Вы, конечно, можете использовать rabbitmq, как вы упомянули, и иметь несколько процессов слушателя, делающих запись. Это будет работать, но я не уверен, что это будет оптимально эффективно. Вам необходимо написать ВСЕ записи, поэтому не обязательно разбивать их, отправлять их в другой процесс, а затем отправлять оттуда в еще один процесс ... Если эти другие процессы не запущены на других машинах.

Если вы читаете данные из файла, который уже записан на диск, и это формат файла, который легко делится (опять же, например, CSV), простой (и очень классический) способ сделать это - разделите размер файла на количество потоков записи. Скажите каждому писателю начальное и конечное смещение файла, который вы хотите обработать. Каждый писатель (кроме начинающего со смещения 0) может искать вперед, пока не найдет разделитель записей (например, \r\n). Затем он начинает считывать и обрабатывать входные записи по одной, пока не выполнит чтение до позиции, равной или превышающей конечное смещение.

Если вы читаете файл из запроса и хотите обработать его вне обработчика запроса, вы можете обнаружить, что более эффективно просто записать его на диск в виде одного большого файла, а затем обработать его потом, как описано выше.

Итак, попробуйте найти способы обработки данных, которые включают наименьшее количество операций чтения и записи. Обрабатывайте данные на месте, если можете, не перемещайте их, если не нужно. Избегайте записи в другие процессы, если они находятся на одной и той же машине, так как этот процесс требует большого объема диска. Если вы хотите, чтобы возможность легко масштабироваться на большее количество машин, попробуйте rabbitmq. Я использую это, это хорошо, и быстро. Но это добавит накладных расходов, поэтому, если вы не получите реальную выгоду от разрушения, это может замедлить вас. Это делает межпроцессное взаимодействие очень простым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...