Рассмотрим некую предметную область, в которой имеются две сущности: category и object. Теперь рассмотрим два типа отношений, которые могут между ними существовать: один-ко-многим и многие-ко-многим.
Отношение один-ко-многим означает, что объект может принадлежать только к одной категории. В реляционной модели данных это отношение представлется добавлением поля category_id в таблицу объектов. При этом можно с лёгкостью:
1) узнать, к какой категории относится объект;
2) получить список объектов, принадлежащих категории.
Отношение многие-ко-многим означает, что объект может находиться в нескольких категориях. В реляционной модели данных это отношение отражается при помощи дополнительной таблицы отношений с полями object_id, category_id. Каждая запись в этой таблице содержит информацию о том “факте”, что объект с ID = object_id находится в категории с ID = category_id.
Для того, чтобы узнать, к каким категориям принадлежит объект или какие объекты содержатся в категории, необходимо делать отдельную выборку по этой таблице.
Если же в предметной области нет необходимости получать информацию о том, какие объекты содержатся в категории, то можно не создавать эту дополнительную таблицу. В этом случае всё, что нам надо получать от этого отношения: список категорий, к которым принадлежит объект. Для этого в таблице объектов можно создать дополнительное поле category_ids, содержащее список ID категорий.
Формат этого списка может быть любым: ID с разделителями, bitmask, внутренний формат какого-нибудь языка (например, serialized array для PHP). Критерий к формату этого дополнительного поля один: удобство использования в CMS.
Отказ от использования дополнительной таблицы в пользу дополнительного поля позволяет сократить количество запросов для получения информации об объекте. Платой за такой обмен является невозможнсть использования внешних ключей и потеря целостности данных (точнее, необходимость ручной поддержки целостности): целостность в обмен на быстродействие.
В идеале front-end CMS должен учитывать тот факт, что данные из этого дополнительного поля могут содержать ID категорий, уже несуществующих в системе, и обрабатывать их соответстенно.
Существует способ получить быстродействие без отказа от целостности данных: завести дополнительное поле не вместо дополнительной таблицы, а в дополнение к ней. Хранить в этом поле следует тоже самое — список ID категорий, к к которым принадлежит объект. В данном случае платой за быстродействие является приобретённая избыточность данных.
Чтобы эта избыточность не привела к противоречивости (когда в поле и в таблице хранятся несовпадающие ID категорий) необходимо поддерживать актуальность поля categoy_ids, которое в данном случае представляет из себя кэш данных из таблицы отношений.
Вася, иди нахуй.
Comment by Val Petruchek — 27.03.2008 @ 16:30
Это ведь называется “денормализация”, да?
Comment by Michael Yakovis — 27.03.2008 @ 17:15
Ага, она самая. Как-то выпало это слово.
Comment by Val Petruchek — 27.03.2008 @ 17:31
Вот интересно: есть какие-нибудь внятные статьи или исследования, описывающие, когда денормализация полезна, а когда вредна? Чтобы они описывали не только выигрыш в скорости работы софта, но и глюки от проблем с потерей целостности данных?
Comment by Сергей Гладилин — 29.03.2008 @ 08:06
Я вообще статей профессиональных девелоперах о таких нюансах почти не встречал. Правда, не особо и искал.
Comment by Val Petruchek — 29.03.2008 @ 12:09