2020-08-09 15:35:56
Всем привет!
Сегодня я хочу поговорить про денормализацию данных. Нормализация предназначена для приведения структуры базы данных к виду, обеспечивающему минимальную логическую избыточность. Всю начальную теорию так или иначе придумал Эдгар Кодд, работавший в IBM. Когда я ещё только учился на Мат-Мехе, мне было известно лишь о 4-х нормальных формах, но сейчас есть и 5-я и 6-я и я даже знаю тех, кто реализовал аналитическую СУБД на уровне 6-й нормальной формы. Подробнее о каждой форме нормализации вы можете почитать сами, я же остановлюсь на том, почему 6-я форма ужасна с точки зрения аналитики.
Итак - 6-я нормальная форма - это «декомпозиция до конца» - избавление от любой избыточности, подход, который упрощает поддержание целостности базы данных, однако работа с самими данными представляет из себя ад. Представьте, что для того, чтобы получить 3 свойства объекта, вам необходимо не только сделать 3 JOIN-а, но ещё и следить в условиях за версионностью этих самых свойств. Мало того, что организация 6-й нормальной формы - процесс трудоёмкий, он ещё и усложняет дальшейшую работу с данными.
В реляционных базах данных так или иначе нормализация более чем оправдана, однако в колоночных аналитических СУБД сценарий работы совершенно другой - так как JOIN-ы дорогие, а транзакционность не требуется. Более того, в колоночных базах данных, например, в ClickHouse происходит поколоночное сжатие данных, а потому денормализация - хорошая затея. Теперь подробней про неё…
Представим, что у нас есть события переходов пользователя по сайту: time, user_id, screen_from, screen_to, event
И представим, что у нас есть таблица с информацией о пользователях - date, user_id, age, sex, country, city
Мы хотим получить в группировке по странам, как пользователи переходят с какого-то экрана на другой, предполагая, например, найти проблемы с переводами или качеством выдачи, - видя разницу в поведении при переходе с одного экрана на другой. Переходов при этом может быть достаточно много, как и самих пользователей, и как следствие JOIN станет очень дорогим.
Идея денормализации заключается в том, чтобы иметь «расширенную» таблицу:
time, user_id, age, sex, country, city, screen_from, screen_to, event
То есть в таблице уже есть вся интересующая нас информация о пользователе - это и есть идея денормализации, - создании избыточности данных ради скорости доступа к ним. Как вы понимаете, если пользователь совершил 100 действий (переходов), то вероятнее всего у него будет 100 строк с одинаковыми age, sex, country, city, однако, как я говорил, при поколоночном сжатии это не такая большая проблема, особенно если сортировка данных содержит в себе user_id - то есть много одинаковых данных лежат рядом и подряд, а соответственно и сжатие работает много лучше.
Идею денормализации данных можно расширить до «хотим в событии иметь всё». То есть не только информацию о пользователе, но и дополнительную информацию об объекте взаимодействия, а также контекст, в котором происходит взаимодействие. Возможно, даже свойства связи объекта и субъекта. Например, если это событие подписки, то можно дополнить колонками типа had_subscription или last_subscription_date - говорящими о том, была ли у пользователя когда-либо подписка, чтобы, например, не перемалывать всю историю для определения того, что пользователь впервые покупает подписку.
Где предел денормализации? На самом деле это большое искусство, которым можно овладеть, продумывая прежде основные и дополнительные аналитические сценарии, которые будут происходить над таблицей. В ВКонтакте я создавал таблицы вплоть до 150 колонок для сырых данных, а также были таблицы и на 1000 колонок для агрегированных - но это ВКонтакте. Большинству компаний, которые я консультировал, такая сильная денормализация не была нужна, а потому зачастую обходились 30-60 колонками.
1.5K viewsSergey Tovmasyan, 12:35