2015-03-07 2 views
0

Я пытаюсь ускорить поиск моих моделей. У меня 3 модели.Django - после внешнего ключа к другому внешнему ключу

class sett(models.Model): 
    setid = models.IntegerField(primary_key=True) 
    block = models.ForeignKey(mapt, related_name='sett_block') 

class data_parsed(models.Model): 
    setid = models.ForeignKey(sett, related_name='data_parsed_setid', primary_key=True, db_index = True) 
    setid_hash = models.CharField(max_length=100, db_index = True) 

class unique_variables(models.Model): 
    setid = models.ForeignKey(sett, related_name='unique_variables_setid', db_index = True) 
    setid_hash = models.CharField(max_length=100, db_index = True) 

Самое главное, что брусчатка имеет первичный ключ с именем SETID, который:

data_parsed и unique_variables имеют внешний ключ SETID

data_parsed: 3 миллиона строк

unique_variables: 13 миллионов строк


Затем у меня есть часть кода, которая пытается перебирать все объекты data_parsed.

def something_1(): 
    timeNow = datetime.datetime.now() 
    for i in range(0,N) <---- N is predefined, and no less than 10 
     for contents in data_parsed.objects.all().iterator(): 
      pass 
    timeEnd = datetime.datetime.now() 
    print str(timeEnd - timeNow) 

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

Теперь, поскольку setid - это те же поля как для data_parsed, так и для unique_variables. Я могу получить элементы в unique_variables с ключом foriegn data_parsed. Следовательно:

def something_2(): 
    timeNow = datetime.datetime.now() 
    for i in range (0, N) <---- N is predefined, and no less than 10 
     for contents in data_parsed.objects.all().iterator(): 
      try: 
       items = unique_variables.objects.get(setid = contents.setid) 
      except: 
       pass 
    timeEnd = datetime.datetime.now() 
    print str(timeEnd - timeNow) 

Однако проблема в том, что это внезапно потребляет часы. Поскольку я не могу использовать select_related, так как я не вернусь к настройке, но на самом деле перейду от установки к unique_variables.

Есть ли способ ускорить получение предметов с таким поведением?


ответ

3

Да, вы можете использовать prefetch_related. Я связал документы для вас.

def something_2(): 
    timeNow = datetime.datetime.now() 
    for i in range (0, N) <---- N is predefined, and no less than 10 
     parsed_objects = data_parsed.objects.all().prefetch_related(
      'setid__unique_variables_setid') 
     for contents in parsed_objects: 
      try: 
       items = list(contents.setid.unique_variables_setid.all()) 
      except: 
       pass 
    timeEnd = datetime.datetime.now() 
    print str(timeEnd - timeNow) 
+0

Для моего собственного любопытства - не 'prefetch_related()' более подходит для 'ManyToMany' поля и' select_related() 'более подходит для' ForeignKey'? – Hybrid

+2

Да, если вы говорите о передовых отношениях, но вы используете ForeignKey для обратного ForeignKey. Обратная сторона ForeignKey - это много: 1, что похоже на ManyToMany. Один '' 'set''' может иметь несколько' '' unique_variables''', ссылающихся на него. Вот почему '' 'prefetch_related''' нужно использовать. – schillingt

+0

Спасибо за ваш ответ! Я смог получить поиск от 1 часа до 20 минут. Я очень ценю вашу помощь! – user1157751

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