2015-02-16 2 views
0

У меня есть приложение django, у которого есть модель (Person), и у меня также есть DB (в таблице есть Appointment), у которых нет определенных моделей (не предназначенных для подключения к приложению django).Как улучшить производительность копирования django mysql?

Мне нужно переместить некоторые данные из таблицы Appointment на номер Person, чтобы вся информация, которую столбец «Люди» должна была отражать в таблице «Назначение». Именно так, потому что существует несколько независимых DB, таких как Appointment, которые нужно скопировать в таблицу Person (поэтому я не хочу делать какие-либо архитектурные изменения в том, как это настраивается).

img

Вот что я делаю сейчас:

res = sourcedb.fetchall() # from Appointment Table 
for myrecord in res: 
    try: 
     existingrecord = Person.objects.filter(vendorid = myrecord[12], office = myoffice)[0] 
    except: 
     existingrecord = Person(vendorid = myrecord[12], office = myoffice) 

    existingrecord.firstname = myrecord[0] 
    existingrecord.midname  = myrecord[1] 
    existingrecord.lastname  = myrecord[2] 
    existingrecord.address1  = myrecord[3] 
    existingrecord.address2  = myrecord[4] 
    existingrecord.save() 

Проблема заключается в том, что это слишком медленно (занимает около 8 минут для 20K записей). Что я могу сделать, чтобы ускорить это?

Я рассмотрел следующий подход:

1. bulk_create: не может использовать это, потому что я должен обновить иногда.

2. удалить все, а затем bulk_create Существует зависимость от модели Person от других вещей, поэтому я не могу удалить записи в модели Person.

3. INSERT ... ON DUPLICATE KEY UPDATE: не может этого сделать, поскольку PK таблицы Person отличается от таблицы назначения PK (первичный ключ). Назначение PK копируется в таблицу Person. Если бы был способ проверить два дублирующих ключа, этот подход будет работать, я думаю.

ответ

0

Несколько идей:

  • EDIT: Смотрите комментарий Trewq к этому и создавать индексы по таблицам в первую очередь ...
  • Заверните все это в транзакции с использованием with transaction.atomic():, так как по умолчанию Django будет создать новую транзакцию на звонок save(), который может стать очень дорогим. С записями 20K одна гигантская транзакция также может быть проблемой, поэтому вам может потребоваться написать код для разделения транзакций на несколько партий. Попробуйте и измерьте!
  • Если RAM не проблема (не должна быть одна с 20k записей), извлечь все данные первой из таблицы назначения, а затем извлечь все существующие объекты Person с использованием одного SELECT запроса вместо одной на каждую запись
  • Использование bulk_create даже если некоторые из них являются обновлениями. Это будет по-прежнему выдавать запросы UPDATE для ваших обновлений, но сократит все ваши запросы INSERT до одного или нескольких, что по-прежнему является улучшением. Вы можете отличить вставки и обновления тем фактом, что вставки не имеют первичного ключа, установленного перед вызовом save(), и сохраните вставки в список Python для более позднего bulk_create вместо их сохранения напрямую.
  • В крайнем случае: напишите необработанный SQL, чтобы сделать использование синтаксиса MySQL INSERT … ON DUPLICATE KEY UPDATE. Для этого вам не нужен такой же первичный ключ, достаточно кода UNIQUE. Ключи могут охватывать несколько столбцов, см. Вариант модели Django Meta.unique_together.
+0

Проблема была в том, что мне нужно было создать индекс - я смог запустить запрос за 76 секунд, и когда я использовал атом(), я смог получить это за 56 секунд. – Trewq

+0

Ну, иногда это проще, чем кто-то думает ... –

Смежные вопросы