Допустим, у меня есть приложение для реляционной базы данных, объект «пользователь» и объект «сообщение». Теперь я хочу показать количество непрочитанных сообщений этому пользователю.
Какой лучший способ архивировать это? Должен ли я ввести поле в пользователя и считать его, если пользователь получает сообщение, и уменьшать счет, если он его читает? Или я выполняю запрос каждый раз, чтобы вычислить количество сообщений для пользователя, помеченных как непрочитанные?
Я думаю, что первый подход более сложен и подвержен ошибкам, но будет работать лучше, чем второй.
Как это обычно делается или какой подход лучше?
database
performance
январь
источник
источник
Ответы:
Лучше всего сначала попробовать без лишнего поля, измерить производительность, и если она действительно окажется слишком медленной, вы попытаетесь оптимизировать. Это может означать переход к первому подходу с использованием дополнительного поля, но вам следует рассмотреть возможность тестирования и других вариантов, например, добавив дополнительный индекс в комбинированные поля («непрочитанные», «userID») в ваших сообщениях.
источник
Решение для учебника в соответствии с теорией базы данных состояло бы в том, чтобы в вашей базе данных не было значений, зависящих от значений других данных, поскольку это переходные зависимости . Наличие полей, которые являются вычисляемыми значениями на основе других полей, является нарушением нормализации, поскольку приводит к избыточной информации.
Однако иногда то, что говорится в учебнике, и какой метод является наиболее практичным на практике, различаются. Подсчет количества непрочитанных сообщений для каждого просмотра страницы может быть довольно дорогой операцией. Кэширование числа в
user
таблице будет намного лучше для производительности. Стоимость может заключаться в том, что в базе данных могут существовать несоответствия: возможно, что сообщение может быть удалено, добавлено или прочитано, не забывая также обновить счетчик непрочитанных сообщений.источник
INSERT
илиDELETE
. (ИлиUPDATE
для учета смены владельца сообщения.). Хорошая СУБД выполнит операцию и запустит триггеры в одной и той же транзакции, поэтому все или ничего не произойдет.Потенциальная проблема - это производительность, а у вас пока нет проблем с производительностью. Есть много вещей, которые вы можете сделать в зависимости от выбранной базы данных, чтобы справиться с этим в решении № 1: индексирование, аппаратное обеспечение, кэширование и т. Д. Все это зависит от того, как часто пользователь должен получать текущий счетчик непрочитанных сообщений. Многие из этих вариантов не требуют настраиваемого кодирования на стороне приложения, поэтому вы можете реализовать их с изменением кода или совсем без него. Облегчает рост с приложением.
Как только пользователь подключается / входит в систему, получение счетчика из базы данных не так уж и плохо. Будет ли ваше приложение постоянно обновлять список сообщений, таких как электронная почта? Отсчет непрочитанных отсчетов отсюда не требует повторного посещения базы данных, а для получения новых сообщений в любом случае потребуется поездка в БД.
Совершаете поездку в БД каждый раз, когда читается сообщение, чтобы пометить IsRead? поля достаточно без пересчета другого поля.
С решением № 2 (ведение счета в поле / на диске), вам понадобится подпрограмма, чтобы периодически перестраивать / пересчитывать это поле при возникновении проблемы? И всегда есть проблемы. Собираетесь ли вы обернуть все это в транзакцию? Каждый раз, когда кто-то отправляет кому-то сообщение, он может потерпеть неудачу, потому что не может обновить UnreadCount принимающего пользователя из-за блокировки таблицы User? Или вы собираетесь создать отдельную таблицу для этого поля?
источник
Я бы сделал это, выполняя каждый раз запрос, т. Е. Ваш второй подход. Просто добавьте индекс в таблицу сообщений для столбца, который действует как внешний ключ к таблице пользователей, чтобы повысить производительность вашего запроса.
Затем, как говорит Док, измерьте эффективность этого подхода, и тогда вы сможете определить, нужно ли вам идти другим путем.
источник