2013-03-07 4 views
3

Мне нужно иметь возможность быстро вставлять большие объемы записей быстро, сохраняя при этом уникальность в базе данных. Новые записи, которые нужно вставить, уже были проанализированы и уникальны. Я надеюсь, что есть способ обеспечить уникальность на уровне базы данных, а не в самом коде.Django Unique Bulk Inserts

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

Массовые вставки в Django не используют метод save, поэтому как можно вставлять несколько сотен до нескольких тысяч записей за раз, сохраняя при этом уникальные поля и уникальные поля вместе?


Мои модели структуры, упрощена, выглядеть примерно так:

class Example(models.Model): 
    Meta: 
     unique_together = (('name', 'number'),) 

    name = models.CharField(max_length = 50) 
    number = models.CharField(max_length = 10) 
    ... 
    fk = models.ForeignKey(OtherModel) 

Edit:

Записи, которые не являются уже в базе данных должна быть вставлена, и записи которые уже существуют, следует игнорировать.

+0

Какая форма ваших исходных данных? Если это csv, мне интересно, можете ли вы просто пропустить каждую запись и сохранить ее таким образом. – djq

+0

['get_or_create'] (https://docs.djangoproject.com/en/1.6/ref/models/querysets/#get-or-create). –

ответ

0

Django сам не применяет атрибут meta unique_together. Это обеспечивается базой данных, используя предложение UNIQUE. Вы можете вставить столько данных, сколько хотите, и вам гарантировано, что указанные поля будут уникальными. Если нет, тогда будет создано исключение (не уверен, какой из них). Более unique_together в docs.

1

Как упоминалось в miki725, у вас нет проблем с вашим текущим кодом. Я предполагаю, что вы используете метод bulk_create. Верно, что метод save() не вызывается при использовании bulk_create, но уникальность полей не применяется внутри метода save(). При использовании unique_together в ограничения уникальности добавляется к базовой таблице в MySQL при создании таблицы:

Джанго:

unique_together = (('name', 'number'),) 

MySQL:

UNIQUE KEY `name` (`name`,`number`) 

Так что, если вы вставляете значение в таблицу, используя любой метод (save, bulk_insert или даже raw sql), вы получите это исключение из mysql:

Duplicate entry 'value1-value2' for key 'name' 

UPDATE:

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

1- Один из вариантов - использовать параметр batch_size для bulk_insert и вставлять данные в несколько партий, чтобы, если один из них вышел из строя, вы пропускаете только остальную часть данных этой партии. (зависит от того, насколько важно вставлять все данные и как часто повторяются записи в двух экземплярах)

2 Еще один вариант - написать цикл for для массовых данных и вставить объемные данные по одному.Таким образом, исключение выдается только для одной строки, а остальные данные вставляются. Это будет каждый раз запрашивать db и, конечно, намного медленнее.

3- Третий вариант - снять уникальное ограничение, вставить данные с помощью bulk_create, а затем написать простой запрос, который удаляет повторяющиеся строки.

+0

Остается ли вставить остальные записи? – NickCSE

+0

@NickCSE plz см. Ответное обновление – jurgenreza

+0

К сожалению, я не могу пропустить ни одну из данных, каждая запись должна внести свой вклад в базу данных. В настоящее время я делаю что-то вроде # 2, и это достаточно медленно, чтобы заставить меня задавать этот вопрос. Я подумал о # 3, но это не выглядит масштабируемым. Каждая объемная вставка может составлять 10 тысяч тысяч записей. – NickCSE