Производительность запросов Django: однонаправленное включение с использованием ForeignKey и двунаправленное с использованием ForeignKey & Related_name - PullRequest
1 голос
/ 17 ноября 2010

Все,

Какой из них вы предпочитаете, когда речь идет о правильном дизайне и чистоте, а также производительности запросов?

Вариант A: (двунаправленная ссылка)

class Country(models.Model):
    name = models.CharField(max_length=128)
    capital = models.ForeignKey('City',related_name="country_capital", null=True)

class State(models.Model):
    name = models.CharField(max_length=128)
    capital = models.ForeignKey('City', related_name="state_capital", null=True)
    country = models.ForeignKey('Country', null=True)

class City(models.Model):
    name = models.CharField(max_length=128)
    state = models.ForeignKey('State', null=True)
    country = models.ForeignKey('Country', null=True)

Вариант B: (однонаправленная ссылка)

class Country(models.Model):
    name = models.CharField(max_length=128)

class State(models.Model):
    name = models.CharField(max_length=128)
    country = models.ForeignKey('Country', null=True)

class City(models.Model):
    name = models.CharField(max_length=128)
    state = models.ForeignKey('State', null=True)
    state_capital = models.BooleanField(default=False)
    country_capital = models.BooleanField(default=False)


Search will be done as:
Get me all cities where name is Waterloo and country is US.
Get me all cities where country is UK.
Get me all states where country is US.
Get me a country where country is US. and capital is Washington DC.
Get me the capital where country is US.

Ответы [ 2 ]

1 голос
/ 17 ноября 2010

Вариант A лучше, потому что он содержит ту же информацию, не требуя набора полей, которые почти всегда будут пустыми (state_capital и country_capital).

Как вы заметили, не в каждой стране есть штаты / провинции, поэтому у вас должны быть поля страны и штатов для модели города. В любом случае, это очень маленькая избыточность для огромного выигрыша, и вы вряд ли столкнетесь с проблемами нормализации (например, очень редко, когда данное государство меняет свою страну). Даже если у каждого города есть ассоциированное состояние в вашей модели, все же лучше добавить избыточное поле для ускорения запроса - тогда вы имеете дело не с одним, а с двумя объединениями таблиц.

Обратите внимание, что Вашингтон, округ Колумбия, состоит из двух мест: города Вашингтона и штата Вашингтон. Итак, ваш запрос:

Получите мне страну, где страна США. и столица - Вашингтон, округ Колумбия.

Следует читать как

Country.objects.filter(code__iexact='US', capital__name__iexact='Washington', capital__state__code__iexact='DC')

(здесь я предполагаю, что для моделей Country и State вы фактически добавляете поле кода для работы с сокращениями)

Я хотел бы отметить, что некоторые из этих запросов кажутся довольно излишними: зачем вам нужно сопоставлять страны как с названиями стран , так и с столицей?

1 голос
/ 17 ноября 2010

С вариантом B, с моей точки зрения, не все в порядке.Во-первых, ничто не мешает двум или более городам быть отмеченными в качестве столицы для определенного штата или страны.Вам необходимо добавить дополнительную проверку в ваши формы, чтобы убедиться, что этого не произошло.

С точки зрения запросов, я думаю, что А все еще предпочтительнее.Например, если вы хотите получить все города в штате, столицей которого является город X, в первом вы должны сделать:

cities = City.objects.filter(state__capital__name="City X")

, а во втором вам нужно будет сделать это:

cities = City.objects.filter(state=City.objects.get(name="City X"))

, который преобразуется в подзапрос, который, вероятно, будет менее эффективным.

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

(* хотя имейте в виду, что это на самом деле не соответствует действительности: так или иначе, не во всех странах есть штаты, и даже в тех странах, где они есть, города, выпадающие за пределы всех штатов, например Канберра в Австралии)

...