Запись данных в Postgresql с низкой производительностью - PullRequest
2 голосов
/ 02 апреля 2019

работает в postgresql У меня есть декартово соединение, производящее ~ 4 миллиона строк. Объединение занимает ~ 5 секунд, а обратная запись в БД - ~ 1 мин 45 с.

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

Использование psycopg2 и панд, чтение данных и выполнение объединения для получения 4 миллионов строк (из ответа здесь: декартово произведение в пандах ) занимает последовательно менее 3 секунд, что впечатляет.

Запись данных обратно в таблицу в базе данных, однако, занимает от 8 минут (лучший метод) до 36 + минут (плюс некоторые методы, которые я отклонил, так как мне приходилось останавливать их после> 1 часа).

Хотя я не ожидал воспроизвести время «только sql», я надеялся бы приблизиться к 8 минутам (я думал, что 3-5 минут не будет неразумным).

Более медленные методы включают в себя:

36 мин. - sqlalchemy`s table.insert (из 'test_sqlalchemy_core' здесь https://docs.sqlalchemy.org/en/latest/faq/performance.html#i-m-inserting-400-000-rows-with-the-orm-and-it-s-really-slow)

13 мин. - psycopg2.extras.execute_batch (https://stackoverflow.com/a/52124686/3979391)

13-15 минут (зависит от размера фрагмента) - pandas.dataframe.to_sql (снова с использованием sqlalchemy) (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html)

Лучший способ (~ 8 минут) - использовать метод cursor.copy_from из psycopg2 (см. Здесь: https://github.com/blaze/odo/issues/614#issuecomment-428332541). Это включает в себя сначала дамп данных в csv (в память через io.StringIO), который сам по себе занимает 2 минуты.

Итак, мои вопросы:

1) У кого-нибудь есть потенциально более быстрые способы записи миллионов строк из кадра данных pandas в postgresql?

2) Документы для метода cursor.copy_from (http://initd.org/psycopg/docs/cursor.html)) утверждают, что исходный объект должен поддерживать методы read () и readline () (отсюда и необходимость в io.StringIO). Предположительно, если DataFrame поддерживает эти методы, мы можем обойтись без записи в CSV. Есть ли способ добавить эти методы?

Спасибо. Giles

1 Ответ

0 голосов
/ 05 апреля 2019

Отвечая на вопрос 1 сам: Кажется, проблема была связана с Postgresql (точнее, с базами данных в целом). Принимая во внимание пункты, сделанные в этой статье: https://use -the-index-luke.com / sql / dml / insert я обнаружил следующее:

1) Удаление всех индексов из таблицы назначения привело к выполнению запроса за 9 секунд. Восстановление индексов (в postgresql) заняло еще 12 секунд, так что все еще значительно ниже других времен.

2) При наличии только первичного ключа вставка строк, упорядоченных по столбцам первичного ключа, сократила время, затрачиваемое примерно на треть. Это имеет смысл, поскольку должно быть небольшое или полное отсутствие перетаскивания строк индекса. Я также убедился, что по этой причине мое картезианское объединение в postgresql было быстрее, во-первых (т.е. строки были упорядочены по индексу, чисто случайно), поместив те же строки во временную таблицу (неупорядоченную) и вставив из нее на самом деле заняло больше времени.

3) Я пытался провести аналогичные эксперименты на наших системах MySQL и обнаружил такое же увеличение скорости вставки при удалении индексов. Однако с mysql казалось, что восстановление индексов израсходовано в любое время.

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

Я все еще задаюсь вопросом, возможно ли удалить шаг записи в csv в python (вопрос 2 выше), так как я полагаю, что тогда я мог бы написать что-то на python, которое было бы быстрее, чем чистый postgresql.

Спасибо, Джайлс

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