сложность обратного поиска внешнего ключа django - PullRequest
0 голосов
/ 28 октября 2018

Предположим, у меня есть такая модель:

    class Post(models.Model):
         name = models.CharField(max_length=25, unique=True)

    class Picture(models.Model):
         post = models.ForeignKey(to=Post, ondelete=models.CASCADE)
         image = models.ImageField()

Теперь предположим, что я делаю запрос примерно так:

    p = Post.objects.get(name=foo)
    images = p.picture_set.all()

Теперь первый запрос, очевидно, просматривает все сообщения наполучить тот, который имеет имя foo.
Но я хотел бы знать о втором.Проводит ли он поиск по всей таблице Picture в базе данных, чтобы найти все изображения с post=p, или информация доступна, когда я получаю p в первом запросе?
Потому что, если это первое, то яЯ обеспокоен проблемами масштабируемости.

1 Ответ

0 голосов
/ 28 октября 2018

Но я хотел бы знать о втором.Проводится ли поиск по всей таблице изображений в базе данных, чтобы найти все изображения с post = p, или информация доступна, когда я получаю p в первом запросе?

Краткий ответ : по умолчанию ForeignKey добавляет индекс, что делает поиск довольно быстрым (логарифмическое по количеству значений и линейное по количеству обратных записей).

Это зависит от того, создает ли база данных индексна ForeignKey.По умолчанию Django будет создавать индекс.Это означает, что он хранит не только строки таблицы, но также структуру данных, которая позволяет быстро искать все строки, имеющие определенное значение.

Реализация индекса может зависеть от базы данных.В MySQL по умолчанию используется BTREE, это означает, что для поиска значения требуется приблизительно O (log n) для получения коллекции и O (k) с k количеством элементов с этим внешним ключом для получения всех.Но существуют и другие структуры индекса, например, какая-то хеш-таблица, которая даже позволяет (немного) ускорить поиск, хотя, например, хеш-таблица не будет настолько эффективной для извлечения всех элементов с ForeignKey меньше заданного числа.

Вы также можете добавить индекс для других столбцов, например:

class Post(models.Model):
    name = models.CharField(max_length=25<b>, db_index=True</b>, unique=True)

Так что теперь получение всех Post объектов с именем с заданным именем также будет выполняться быстрее.

Использование индексов, конечно, не «бесплатно»: это означает, что каждый раз, когда вы вставляете или удаляете запись, индекс также должен изменяться (обычно для этого также требуется O (log n) ).Если вы обновляете запись, изменяя значение внешнего ключа, этот индекс также необходимо изменить.Таким образом, индексы обеспечивают значительное ускорение, но следует стремиться размещать индексы только в столбце, для которого часто выполняется поиск, поскольку в противном случае стоимость «обслуживания» индекса может быть больше, чем выигрыш от ускорения процесса поиска.

...