Внешний ключ во время выполнения в сравнении с целочисленным полем
У меня есть проблема. У меня уже есть два решения для моей проблемы, но мне интересно, какое из них быстрее. Я предполагаю, что второе решение не только более удобно в использовании, но и быстрее, но я хочу быть уверенным, поэтому и спрашиваю. Моя проблема в том, что я хочу сгруппировать несколько строк вместе. Группа не будет содержать никаких метаданных. Поэтому меня интересует только время выполнения.
С одной стороны, я могу использовать поле Integer и фильтровать его позже, когда мне нужно получить все записи, принадлежащие группе. Я предполагаю, что время выполнения O(n).
class SingleEntries(models.Model):
name = models.CharField(max_length=20)
group = models.IntegerField(null=True)
def find_all_group_members(id):
return SingleEntries.objects.filter(group=id)
Второе решение и, вероятно, более практичный способ - создать внешний ключ к другой модели, используя только pk там. Затем я могу использовать обратное отношение, чтобы найти все записи, которые принадлежат группе.
Первый более эффективен, так как в этом случае будет использоваться один запрос, в то время как во втором случае сначала будет получен Group
, а затем еще один для SingleEntries
.
Действительно, если вы работаете с:
SingleEntries.objects.filter(group=id)
это сделает простой запрос:
SELECT appname_singleentries.* FROM appname_singleentries WHERE appname_singleentries.group_id = id
Таким образом, не сначала забирает Group
в память.
Однако последний будет делать два запроса. Действительно, сначала будет сделан запрос для получения Group
, а затем будет сделан запрос, подобный приведенному выше, для получения SingleEntries
.
Семантически эти две группы также не совсем одинаковы: если такой группы нет, то первая вернет empty QuerySet
, тогда как вторая вызовет исключение Group.DoesNotExists
.
Но вы можете смоделировать это с помощью:
class Group(models.Model):
pass
class SingleEntries(models.Model):
name = models.CharField(max_length=20)
group = models.ForeignKey(Group,on_delete=models.CASCADE,null=True)
def find_all_group_members(id):
return SingleEntries.objects.filter(group_id=id)
Таким образом, вы можете использовать Group
модель без необходимости сначала получить Group
Если группы статичны по своей природе, то есть если вы не видите, что в вашей системе появляется больше групп, вы можете использовать choices в Django.
Определите варианты выбора следующим образом
class GroupType(models.IntegerChoices):
GROUP_0 = 0, "Group 0 name"
GROUP_1 = 1, "Group 1 name"
GROUP_2 = 2, "Group 2 name"
И используйте его как поле выбора в модели SingleEntries
, как показано ниже
class SingleEntries(models.Model):
name = models.CharField(max_length=20)
group = models.IntegerField(choices=GroupChoices.choices, default=<set default here>)
Если группы динамические, то есть пользователи могут создавать группы, когда захотят, в этом случае используйте второй подход - иметь другую модель для группы.