Самый эффективный способ вставки тысяч записей в таблицу (MySQL, Python, Django)

У меня есть таблица базы данных с уникальным строковым полем и несколькими целыми полями. Поле строки обычно составляет 10-100 символов.

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

[("hello", 3, 4), ("cat", 5, 3), ...]

Мне нужно вставить все эти кортежи в таблицу (предположим, что я не подтвердил, что ни одна из этих строк не появляется в базе данных). Для пояснения я использую InnoDB, и у меня есть автоматически инкрементный первичный ключ для этой таблицы, строка не является PK.

Мой код в настоящее время выполняет итерацию через этот список, поскольку каждый кортеж создает объект модуля Python с соответствующими значениями и вызывает ".save()", примерно так:

@transaction.commit_on_success
def save_data_elements(input_list):
    for (s, i1, i2) in input_list:
        entry = DataElement(string=s, number1=i1, number2=i2)
        entry.save()

Этот код в настоящее время является одним из узких мест в моей системе, поэтому я ищу способы его оптимизации.

Например, я мог генерировать SQL-коды, каждый из которых содержит команду INSERT для 100 кортежей ( "жестко закодированных" в SQL) и выполнять ее, но я не знаю, улучшит ли она что-нибудь.

Есть ли у вас предложение оптимизировать такой процесс?

Спасибо

Ответ 1

Вы можете записать строки в файл в формате "field1", "field2",.. и затем используйте LOAD DATA для их загрузки.

data = '\n'.join(','.join('"%s"' % field for field in row) for row in data)
f= open('data.txt', 'w')
f.write(data)
f.close()

Затем выполните следующее:

LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;

Ссылка

Ответ 2

Для MySQL, в частности, самый быстрый способ загрузки данных - это LOAD DATA INFILE, поэтому, если вы можете преобразовать данные в формат, который ожидает, вероятно, это самый быстрый способ получить его в таблице.

Ответ 3

Если вы не LOAD DATA INFILE, как упоминают некоторые другие предложения, две вещи, которые вы можете сделать, чтобы ускорить ваши вставки:

  • Используйте подготовленные операторы - это сокращает накладные расходы на разбор SQL для каждой вставки
  • Сделайте все свои вставки в одной транзакции - для этого потребуется использовать механизм БД, поддерживающий транзакции (например, InnoDB)

Ответ 4

Если вы можете сделать ручную инструкцию INSERT, то как я пойду. Единственный оператор INSERT с несколькими предложениями с параметрами намного быстрее, чем множество отдельных INSERT операторов.

Ответ 5

Независимо от метода вставки, вы хотите использовать движок InnoDB для максимального чтения/записи concurrency. MyISAM блокирует всю таблицу в течение времени вставки, тогда как InnoDB (в большинстве случаев) будет блокировать только затронутые строки, позволяя операторам SELECT продолжить.

Ответ 7

Это не связано с фактической загрузкой данных в БД, но...

Если вы предоставляете "Данные загружаются... Нагрузка будет выполнена в ближайшее время" тип сообщения пользователю является опцией, тогда вы можете запускать INSERT или LOAD DATA асинхронно в другом потоке.

Просто что-то еще, чтобы рассмотреть.

Ответ 8

Я не знаю точных деталей, но вы можете использовать представление данных стиля json и использовать его в качестве светильников или чего-то еще. Я видел что-то подобное на Django Video Workshop Дугласа Наполеона. Смотрите видео в http://www.linux-magazine.com/online/news/django_video_workshop. и http://www.linux-magazine.com/online/features/django_reloaded_workshop_part_1. Надеюсь, что это поможет.

Надеюсь, вы сможете это исправить. Я только начал изучать django, поэтому могу просто указать вам ресурсы.