Сколько стоят многие нуль-внешние ключи в модели? - PullRequest
1 голос
/ 11 июля 2019

У меня есть модель Post, модель Image и модель Channel.У меня есть внешний ключ в модели Image, связанный с моделью Post.Кроме того, я пытаюсь добавить обнуляемый внешний ключ, связанный с моделью канала.

   class Image(models.Model):
        post = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
        comment = models.ForeignKey(Comment, null=True, blank=True, on_delete=models.CASCADE)
        news = models.ForeignKey(News, null=True, blank=True, on_delete=models.CASCADE)
        message = models.ForeignKey(Message, null=True, blank=True, on_delete=models.CASCADE)

        channel = models.ForeignKey(Channel, null=True, blank=True, on_delete=models.CASCADE)
        file = ProcessedImageField(upload_to='uploads/%Y/%m/%d/',
                                    processors=[Transpose()],
                                    format='JPEG',
                                    options={'quality': 50},
                                    blank=True)

Меня беспокоит, что поле канала будет в основном нулевым, поскольку мне нужно только одно изображение на канал.Но изображение должно быть связано с постом.Таким образом, каждый канал имеет одно изображение, которое связано с постом.Однако сообщений и изображений будет несоизмеримо больше, чем канала, поэтому поле канала в модели изображения будет потрачено впустую большую часть времени.

Другое решение, о котором я подумал, - это создание новой модели изображения исключительно дляМодель канала и при создании нового экземпляра изображения вручную скопируйте изображение из исходного экземпляра, связанного с пост-изображением.

class ChannelImage(models.Model):
            channel = models.OneToOneField(Channel)
            post = models.OneToOneField(Post)
            file = ProcessedImageField(upload_to='uploads/%Y/%m/%d/',
                                        processors=[Transpose()],
                                        format='JPEG',
                                        options={'quality': 50},
                                        blank=True)
//copy a file from the original post

Поэтому мой вопрос заключается в том, какова стоимость того, что в таком количестве теряются пустые внешние ключимодель есть?Можно ли использовать в модели много потерянных внешних ключей?

Ответы [ 2 ]

2 голосов
/ 11 июля 2019

Прежде всего

Технически нет ничего плохого в том, чтобы иметь модель со свойством с нулевым значением во многих строках.

О вашем дизайне

Вы говорите о двух конструкциях:

Image -> Channel  ( image references channel )
ChannelImage -> Image ( new model to store  channel image )

Но в своем посте вы говорите:

Таким образом, у каждого канала есть одно изображение, которое связано с почтой.

Но, что не так?

Channel -> Image ( channel reference image )

При таком подходе вы не потеряете информацию, потому что Image все еще подключен к Post.

Ответ

На мой взгляд, это так:

  1. Примените нормализацию базы данных к вашему сценарию.
  2. Изменить естественные ключи на Суррогатные ключи (идентификаторы). Может быть, вы хотите сохранить некоторые естественные ключи.
  3. Убедитесь, что в вашем дизайне нет проблем с производительностью (возможно, вам нужно объединить некоторые данные в поле, чтобы ускорить выполнение некоторых запросов). Нулевые значения не являются проблемой производительности.

Бонус-трек

Поскольку в django 2.2 вы можете написать условие индекса , это означает, что, если вам нужно проиндексировать модель по свойству с большим количеством нулей, вы можете индексировать, если хотите, только для строк с некоторое значение в этом свойстве, например, не нуль.

Если таблица очень большая и ваши запросы в основном нацелены на подмножество строк, может быть полезно ограничить индекс этим подмножеством. Укажите условие как Q. Например, условие = Q (pages__gt = 400) индексирует записи с более чем 400 страницами.

0 голосов
/ 11 июля 2019

При рассмотрении стоимости необходимо учитывать два основных аспекта;время и память.

Есть хорошая запись о стоимости внешнего ключа для postgresql.Выполняется проверка влияния внешних ключей на производительность по времени, когда присутствует только один динамический параметр.Результаты приведены ниже:

Единственный параметр, который принимает эта функция, - это количество таблиц, которые она должна создать, ссылающихся на эту исходную таблицу.[...] эти моменты времени собирались несколько раз, и в среднем составляли 2961 мс, 3805 мс, 4606 мс, 5089 мс и 5785 мс после трех прогонов каждый.Как мы видим, после пяти внешних ключей производительность наших обновлений падает на 28,5%.К тому времени, когда у нас будет 20 внешних ключей, обновления будут на 95% медленнее!

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...