2015-04-20 5 views
1

Мне нужно создать много уникальных кодов и вставить их в базу данных.Массовая вставка в базу данных уникальных кодов

Конечно, я могу написать что-то вроде этого:

codes = set() 
while len(codes) < codes_size: 
    c = generate_code() 
    if len(Codes.objects.filter(code=c)) == 0: 
     codes.add(Codes(c)) 
Codes.objects.bulk_create(codes) 

Но когда база данных уже содержит много кодов работает очень медленно.

Если код вставки после каждого поколения - это очень медленно.

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

bulk_create не указывать какой код повышать исключение.

+0

Использование 'not Code.objects.filter (code = c) .exists()' вместо 'len (Codes.objects.filter (code = c)) == 0' повысит эффективность вашего кода, даже если он не отвечает на ваш вопрос. – aumo

ответ

1

Мое понимание состоит в том, что bulk_create() выполняет его операцию в рамках операции , которая не совершена, если произошла ошибка. Это означает, что либо все вставки преуспели, либо none преуспел.

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

С точки зрения исключений вы, скорее всего, получите подкласс django.db.utils.DatabaseError, например. django.db.utils.IntegrityError. Поскольку вы не знаете, какая ошибка базы данных будет поднята, вы должны поймать DatabaseError.

Я не думаю, что есть какой-либо способ узнать из исключения, какой из кодов вызвал проблему.

Один из способов справиться с этим, чтобы генерировать все коды фронт, а затем, в течение transaction, испытание ли они уже существуют в таблице на одном дыхании с помощью filter() и вставить их, если нет дубликатов:

from django.db import transaction 

codes = set() 
while len(codes) < codes_size: 
    codes.add(generate_code()) 

with transaction.atomic(): 
    # check for any duplicate codes in table... 
    dups = Codes.objects.filter(code__in=codes) 
    if len(dups): 
     print 'Duplicate code(s) generated: {}'.format(dup.code for dup in dups) 
     # remove dups from codes, and generate additional codes to make up the shortfall. 
     # Note that this might also result in duplicates.... 
    else: 
     Codes.objects.bulk_create(Codes(code) for code in codes) 

Вам все равно нужно обрабатывать исключения баз данных, которые не связаны с повторяющимися значениями. Для простоты я оставил это.

+0

'dups = Codes.objects.filter (code__in = codes)' это открытие для меня. Спасибо. – HotIceCream

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