Psycopg2, Postgresql, Python: самый быстрый способ массовой вставки
Я ищу наиболее эффективный способ массовой вставки нескольких миллионов кортежей в базу данных. Я использую Python, PostgreSQL и psycopg2.
Я создал длинный список tulpes, которые должны быть вставлены в базу данных, иногда с модификаторами, такими как geometric Simplify
.
наивный способ сделать это будет строковое форматирование списка INSERT
операторы, но есть три других метода, о которых я читал:
- используя
pyformat
привязка стиле для параметрического вставки - используя
executemany
в списке кортежей и - использование записи результатов в файл и использование
COPY
.
кажется, что первый способ наиболее эффективен, но я был бы признателен за ваши идеи и фрагменты кода, рассказывающие мне, как это сделать правильно.
8 ответов
Да, я бы проголосовал за копию, при условии, что вы можете написать файл в сервержесткий диск (не диск, на котором работает приложение), поскольку копия будет считываться только с сервера.
есть новый руководство psycopg2 содержит примеры для всех опций.
на скопировать вариант самый эффективный. Тогда executemany. Затем выполнить с pyformat.
по моему опыту executemany
не быстрее, чем запуск многих вставок самостоятельно,
самый быстрый способ-отформатировать один INSERT
многие ценности, может в будущем executemany
улучшится, но пока это довольно медленно
Я подкласс a list
и перегрузить метод добавления, поэтому, когда список достигает определенного размера, я форматирую вставку, чтобы запустить ее
можно использовать новая библиотека upsert:
$ pip install upsert
(можно pip install decorator
первая)
conn = psycopg2.connect('dbname=mydatabase')
cur = conn.cursor()
upsert = Upsert(cur, 'mytable')
for (selector, setter) in myrecords:
upsert.row(selector, setter)
здесь selector
- это dict
объект {'name': 'Chris Smith'}
и setter
это dict
как { 'age': 28, 'state': 'WI' }
это почти так же быстро, как писать пользовательский код вставки [/UPDATE] и запускать его напрямую с помощью psycopg2
... и он не взорвется, если строка уже существует.
первый и второй будут использоваться вместе, а не отдельно. Третий был бы самым эффективным сервером, хотя, поскольку сервер будет делать все тяжелая работа.
любой, кто использует SQLalchemy, может попробовать версию 1.2, которая добавила поддержку bulk insert для использования psycopg2.дополнительный.execute_batch () вместо executemany при инициализации движка с use_batch_mode=True как:
engine = create_engine(
"postgresql+psycopg2://scott:tiger@host/dbname",
use_batch_mode=True)
http://docs.sqlalchemy.org/en/latest/changelog/migration_12.html#change-4109
тогда кому-то придется использовать SQLalchmey не будет беспокоиться, чтобы попробовать различные комбинации sqla и psycopg2 и direct SQL вместе.
очень связанный вопрос:массовая вставка с SQLAlchemy ORM
все дороги ведут в Рим, но некоторые из них пересекает горы, требует паромов, но если вы хотите быстро просто выехать на трассу.
в этом случае автомагистраль должна использовать execute_batch() особенность psycopg2. В документации сказано это лучше всего:
текущая реализация executemany()
is (используя чрезвычайно благотворительное преуменьшение) не особенно эффективно. Эти функции можно использовать для ускорения повторного выполнения инструкции по набору параметров. За счет уменьшения количества серверных раундтрипов производительность может быть на порядок лучше, чем при использовании executemany()
.
в моем собственном тесте execute_batch()
и в два раза быстрее as executemany()
, и дает возможность настроить page_size для дальнейшей настройки (если вы хотите сжать последние 2-3% производительности от драйвера).
та же функция может быть легко включена, если вы используете SQLAlchemy, установив use_batch_mode=True
в качестве параметра при создании двигателя с create_engine()