Я провел несколько тестов на Django 1.10 / Postgresql 9.4 / Pandas 0.19.0 и получил следующие тайминги:
- Вставьте 3000 строк по отдельности и получите идентификаторы из заполненных объектов, используя Django ORM: 3200ms
- Вставьте 3000 строк с пандами
DataFrame.to_sql()
и не получите идентификаторы: 774ms
- Вставьте 3000 строк с помощью менеджера Django
.bulk_create(Model(**df.to_records()))
и не получите идентификаторы: 574ms
- Вставьте 3000 строк с буфером
to_csv
в StringIO
и COPY
(cur.copy_from()
) и не получите идентификаторы: 118ms
- Вставьте 3000 строк с
to_csv
и COPY
и получите идентификаторы с помощью простого SELECT WHERE ID > [max ID before insert]
(возможно, не поточно-ориентированный, если COPY
не удерживает блокировку таблицы, предотвращающую одновременные вставки?): 201ms
def bulk_to_sql(df, columns, model_cls):
""" Inserting 3000 takes 774ms avg """
engine = ExcelImportProcessor._get_sqlalchemy_engine()
df[columns].to_sql(model_cls._meta.db_table, con=engine, if_exists='append', index=False)
def bulk_via_csv(df, columns, model_cls):
""" Inserting 3000 takes 118ms avg """
engine = ExcelImportProcessor._get_sqlalchemy_engine()
connection = engine.raw_connection()
cursor = connection.cursor()
output = StringIO()
df[columns].to_csv(output, sep='\t', header=False, index=False)
output.seek(0)
contents = output.getvalue()
cur = connection.cursor()
cur.copy_from(output, model_cls._meta.db_table, null="", columns=columns)
connection.commit()
cur.close()
Статистика производительности была получена для таблицы, уже содержащей 3000 строк, работающих на OS X (i7 SSD 16 ГБ), в среднем из десяти запусков с использованием timeit
.
Я возвращаю мои вставленные первичные ключи, назначая идентификатор пакета импорта и сортируя по первичному ключу, хотя я не на 100% уверен, что первичные ключи всегда будут назначаться в том порядке, в котором строки сериализуются для команды COPY
- был бы признателен за мнения в любом случае.