Первый раз я столкнулся с намеренной денормализацией около года назад (на самом деле уже больше, статья давно в черновиках). В то время мы (Orange[UC]e) занимались оптимизацией скорости работы нашего JavaFX клиента. В одном из отчетов необходимо было осуществлять поиск по последним цифрам номеров телефонов. А в БД номера телефонов хранились в прямом виде. К моему большому сожалению, MariaDB (форк MySQL) не имеет возможности использовать индексы при поиске по концу строки (а номера у нас хранились в виде строк). Решение данной проблемы стало добавление столбца с перевернутым номером телефона, и добавлением индекса для этого столбца. Столбец с «прямым» номером решили тоже оставить, т.к. времени на переписывание логики на использование только перевернутого номера не было. Таким образом у нас получилось 2 столбца, которые содержат одни и те же данные.
Последний раз с денормализацией для увеличения производительности я столкнулся совсем недавно (около трех месяцев назад). Здесь все получилось намного интереснее. Подробности под катом.
Для начала опишем схему БД, с которой возникла проблема. Не знаю, могу ли я описывать реальную структуру, поэтому придумаем свою. Допустим у нас имеется 2 таблицы: main, minor. ER-модель схемы на рисунке ниже. В этих таблицах хранятся миллионы записей.
Для отчета нужны обе эти таблицы, заджойненные по main_id. Для фильтрации нужно использовать и main.timestamp и minor.phone_number (причем возможны ситуации когда нужно только что-то одно из двух). Пока в таблицах было менее миллиона строк — все было в порядке. Дальше отчеты строились все медленнее и медленнее. В какой то момент производительность упала ниже плинтуса. Эту проблему нужно было решать.
Решение было найдено достаточно быстро — денормализация. Мы просто добавили дублирующее поле timestamp в minor. И сделали составной индекс. Соответственно, теперь можно очень быстро выбирать только необходимые данные из таблицы minor и джойнить их с данными с таблицы main. А, когда нам необходимо получить только данные по timestamp — мы все еще можем использовать таблицу main.
Кстати говоря, не стоит думать что описанный в этой статье вид денормализации — единственный. Их столько же сколько и условий, выполнение которых необходимо, для того, чтобы переменная отношения могла находиться в какой-либо нормальной форме. Говоря проще, денормализовали — уровень нормальной формы понизился 🙂
П.С. Сам я не очень положительно отношусь к денормализации, но иногда без нее — никак.