Александр Кротов | Наталья Носенко

Универсальные структуры
в реляционных БД

Универсальная структура реляционной БД.
Разница между универсальной и неуниверсальной структурой БД.
Подходы к проектированию реляционной БД.
Когда концепция EAV оправдана.
Введение
Статья будет полезна аналитикам и начинающим разработчикам для выбора общего подхода к проектированию баз данных и понимания сложностей, которые иногда возникают при развитии БД ИТ-проекта. Отталкиваясь от приведённых примеров систем и ситуаций, вы сможете на этапе проектирования предусмотреть в структуре вашей базы данных некоторые особенности, которые позволят впоследствии при необходимости гибко реагировать на изменение предметной области.

В конце данной статьи упоминается концепция EAV — Entity-Attribute-Value, которая рассматривается на простых примерах в реляционной БД. Считается, что подход EAV имеет ряд недостатков и не является рекомендованным по умолчанию. Мы обсудим ситуации, когда он оправдан и применим, или, как минимум, когда его стоит рассмотреть на этапе проектирования. Говоря простыми словами, такой способ хранения данных — это реализация принципа noSQL средствами РСУБД — можно сказать, что именно так выглядел «noSQL 20 лет назад» — до того, как придумали noSQL базы данных.

Время на чтение статьи: 25 минут
Лень читать? Посмотрите видео.

Как выбирать структуру базы
данных для проекта
Структуру базы данных формируют на основе требований к использующей её информационной системе в целом, причём любой вид функциональных или нефункциональных требований может прямо или косвенно повлиять на будущую структуру базы данных. В результате, в подавляющем большинстве случаев, структура БД находится в рамках определённой предметной области и оказывается точно ориентированной на конкретную систему и требования к ней. Данные из предметных областей, существенно отличающихся от выбранной, в такую базу данных разместить будет крайне сложно или невозможно.

Другими словами, традиционные реляционные базы данных являются специализированными для предметной области или НЕуниверсальными.
Признаки неуниверсальных структур БД:

  1. Каждая таблица базы данных соответствует определённой сущности предметной области
  2. Каждая запись в таблице соответствует определённому экземпляру сущности
  3. Каждое поле таблицы соответствует определённому атрибуту определённого экземпляра определённой сущности

Когда аналитик начинает описывать модель данных, такой подход следует применять в первую очередь. Он позволяет спроектировать модель, чётко соответствующую конкретной предметной области. Так, чтобы, как у хорошей хозяйки на кухне, каждый ножик, каждая ложка и вилка лежали на своём положенном месте, чтобы было удобно находить необходимый предмет и эффективно пользоваться всей созданной конструкцией.

Рассмотрим пример — представим, что нам заказали разработку CRM для системы регистрации автомобилей. Начнём с анализа предметной области.
Пример проектирования модели БД
на основе понимания предметной области «регистрация автомобиля»
При проектировании традиционных, неуниверсальных структур БД аналитик приходит от описания предметной области к её концептуальной модели, выделяя сущности, атрибуты, связи между сущностями и проецирует созданную концептуальную модель на логическую модель базы данных. (Замечание: зачастую фаза формализации предметной области и создания концептуальной модели в чистом виде опускается и аналитик сразу создаёт логическую модель, исходя из собственного представления о предметной области. Не будем комментировать, насколько такой подход правильный, но так бывает довольно часто).

Разберём пример специализированной модели на примере БД для CRM для процесса регистрации автомобилей.

Исходя из личного жизненного опыта, легко представить, что в предметной области существует человек — владелец автомобиля, автомобиль — принадлежащий этому человеку объект, и свидетельство о регистрации — та самая «розовая бумажка» — документ, подтверждающий принадлежность данного автомобиля владельцу.

Пример создания НЕуниверсальной структуры
Каждой сущности и предметной области соответствует одна или более сущностей модели данных. На иллюстрации мы видим сущности «автомобиль», «свидетельство о регистрации» и «человек» (объекты жёлтого цвета).

Затем для каждой сущности мы будем добавлять связанные сущности и атрибуты — например, у автомобиля есть цвет (атрибут) и модель автомобиля (сущность, с которой связаны другие сущности — тип транспортного средства, марка автомобиля и так далее). Атрибуты «марка автомобиля» или «цвет» — следует реализовать в виде справочников, так как их перечень ограничен и известен заранее. Так постепенно будут добавляться недостающие атрибуты, появляться связи таблиц через ключи и другие элементы. Модель приобретёт более полный вид, например, как на иллюстрации ниже.

Доработанная логическая модель БД CRM для регистрации автомобилей для ключевых сущностей.

НЕуниверсальная структура БД для предметной области «регистрация автомобилей»
Постепенно аналитик создаёт полноценную логическую модель, которая на следующем шаге может быть преобразована в физическую, и дальше отправится в конкретную систему управления базами данных.

К сожалению, проектировать подобным образом специализированную структуру БД, исходя из понятной модели предметной области, получается отнюдь не всегда. Далее мы рассмотрим несколько ситуаций, когда такой узконаправленный подход оказывается либо неудобным, либо вообще неподходящим.
Когда приходится применять
универсальную структуру БД (наподобие EAV)
Под неопределённым составом мы понимаем ситуацию, когда у ключевых, особенно важных сущностей предметной области, очень много атрибутов, и мы не можем быть до конца уверены, что такой состав атрибутов будет постоянным. Бывают ситуации, когда у сущности могут появиться новые атрибуты или перестать действовать какие-то старые.
Сценарий 1.
Неопределённый состав атрибутов сущности предметной области
Пример 1. Химические анализы минералов

Сегодня периодическая таблица Менделеева содержит 118 химических элементов, причём четыре из них появились в ней, по меркам науки, совсем недавно — в 2016 году, и человечество надеется продолжить открывать новые элементы.

При научной и экспериментальной работе исследователям приходится определять и исследовать не только конкретные элементы, но и различные соединения, элементы в разных валентностях, изотопы одного и того же элемента, и изучать их поведение в разных условиях. Количество показателей, которые можно определять различными аналитическими методами для разных химических веществ и природных объектов — просто огромно: определяются сотни или даже тысячи разных показателей. Но самое главное — то, что мы не знаем, какие методы появятся завтра, и какие показатели учёные смогут определять с помощью этих новых методов.
Пример 2. Состав продуктов питания

Человек, который следит за своим здоровьем, когда видит незнакомый продукт на полке магазина, первым делом изучает состав ингредиентов, чтобы узнать, сколько там белков, жиров, углеводов, сахара, каких-нибудь красителей, заменителей, консервантов, окислителей и так далее. Так же, как и описанием химических веществ, мы имеем дело с огромным количеством всевозможных показателей и не знаем, какие новые показатели появятся в этом перечне завтра.
Пример 3. Состав полей финансовой отчётности

Все мы знаем, как выглядит финансовая отчётность: это набор форм или таблиц, каждая из которых содержит определённые показатели бизнеса компании. Каждое поле таблицы содержит конкретное значение.

Финансовая отчётность
На иллюстрации изображены фрагменты таких форм — даже в них много десятков ячеек, а если собрать полностью все формы из отчёта одной компании, то мы получим несколько сотен показателей. Давайте разберёмся, каким образом можно все эти показатели уложить в таблицы реляционной базы данных.
Выбор между широкой и узкой таблицей
при проектировании отчётности
Представим, что нам нужно спроектировать структуру для хранения данных по финансовой отчетности компании. Первое, что нужно решить — в какой вид таблицы уложить эти данные — назовем их «простыня» (широкая таблица) или «портянка» (узкая таблица).

«Простыня» (широкая таблица) — это таблица, где много полей (столбцов) и относительно мало записей (строк).

Широкая таблица (много полей, мало записей)


Структура БД для финансовой отчётности в широкой таблице

В такой структуре одному финансовому отчёту соответствует одна запись (строка) в таблице, а одному значению бизнес-показателя — одна ячейка в соответствующем поле (столбце). Показателей может быть очень много, поэтому атрибутов и, соответственно, столбцов в таблице в нашем примере более 200, и это не предел — их может оказаться и 500, и тысяча. Главное, чтобы СУБД позволяла поддерживать такое количество полей. В примере, как вы видите, все столбцы имеют абстрактные названия — можете вместо «Атрибут 202» представить название любого показателя, например «остатки по счетам клиентов-юрлиц» и так далее.

Пример данных финансовой отчётности в широкой таблице
Удобство широкой таблицы для отчётности состоит в том, что примитивным SQL-запросом можно получить сразу весь отчёт со всеми его показателями:

SELECT FROM {название широкой таблицы} WHERE {ключ} = {номер нужного отчёта}

Состав показателей отчётности определяется нормативными или законодательными документами, и эти требования периодически меняются — вспомним, например, как часто появляются новые требования к отчётности со стороны налоговой инспекции. При добавлении нового показателя в форму отчётности придётся добавить новое поле в существующую таблицу, либо создать новую таблицу. После этого придётся пересмотреть все объекты базы данных, которые обращаются к этой таблице (представления, процедуры, функции и т.д.), а также адаптировать программный код, который обращается к этим объектам базы данных, и дальше по всей вертикали с самого низа (самой БД) до «верха» — экранных форм пользователя. Подобного рода изменения в работающей информационной системе очень затратны, поэтому там, где можно, стараются их избежать.
Узкая таблица (мало полей, много записей)

Узкая таблице («портянка») имеет немного иной вид, и по структуре уже напоминает реализацию принципа «ключ-значение», который используется в самых разных подходах и технологиях, например, в некоторых типах noSQL баз данных или в JSON-документах. Однако, мы спроектируем нечто подобное, оставаясь строго в рамках реляционной БД.

Структура БД для финансовой отчётности в узкой таблице
Сначала опишем нормативно-справочную часть, а именно: формы отчётности, строки, содержащие показатели, и конкретные показатели (на диаграмме обозначено зелёным). Далее спроектируем ту часть структуры, которая соответствует данным о конкретных компаниях и их отчётах (на диаграмме обозначено жёлтым).

Давайте посмотрим, как могут выглядеть данные, размещённые в таблицах с такой структурой (зелёным на рисунке обозначены ключевые поля — здесь ключ составной).

Пример данных финансовой отчётности в узкой таблице
Для одного отчёта нужно будет создать такое количество записей в таблице, сколько показателей присутствует в отчёте — хоть тысячу. Причём если появится новая форма или показатель, мы легко добавим их в справочные таблицы и сможем вводить значения для новых показателей в ту же самую таблицу, не изменяя её структуру.

Недостатки узких таблиц

Наряду с очевидными достоинствами, у описанного подхода есть и очевидные недостатки. Во-первых, в реальной жизни, в отличие от приведённого нами примера с числовыми значениями показателей, отнюдь не всегда получается уложить все показатели в поле с одним и тем же типом данных. Во-вторых, спроектированная даже таким образом БД не защищена от потребности в радикальном изменении структуры в случае, если требования к формату отчётности изменятся по внешним причинам.
Сценарий 2.
Необходимость объединения сущностей,
различающихся по атрибутивному составу
В жизни нередко встречаются ситуации, когда в общих бизнес-процессах участвуют сущности, заметно различающиеся по атрибутивному составу.

Пример 1. Работа с разными типами клиентов компании

С одной стороны, действия с разными типами клиентов компания производит во многом одни и те же: например, может выставить клиенту счёт, сделать скидку, внести в список особо важных клиентов или, наоборот, занести в чёрный список. С другой стороны, клиент может быть юридическим лицом, физическим лицом, самозанятым, индивидуальным предпринимателем, или вообще юрлицом в юрисдикции иностранного государства. И у всех этих типов клиентов будут разные наборы атрибутов, мало пересекающиеся между собой.
Пример 2. Комплект документов, сопровождающих сложный бизнес-процесс

Представим некий сложный бизнес-процесс, например, таможенное оформление. Декларант представляет к своему грузу множество документов: собственно таможенную декларацию, различные заявления, расписки, сертификаты, договора, банковские гарантии и так далее. С виду все эти документы очень похожи, и с ними выполняются близкие по смыслу действия: их можно подписать, утвердить или отменить, но состав реквизитов для разных типов документов — очень разный.

Пример 3. Каталог музейного фонда

Разберём этот пример подробнее.
Попробуем вначале использовать широкую таблицу из прошлого примера, то есть применить подход «много полей, мало записей». Заполненная данными таблица по всем музейным экспонатам будет иметь следующий вид.

Пример данных каталога музейного фонда в широкой таблице
Атрибуты, общие для всех сущностей (например, регистрационный номер экспоната и дата его добавления в коллекцию), будут заполнены, как показано в зеленых полях. Однако, поля для специфических атрибутов каждой группы будут заполнены у одной группы, при этом оставаясь пустыми у всех записей из других групп, так как не применимы к ним. Значительная часть полей в таблице будет оставаться пустой.

С точки зрения реляционных баз данных подобные таблицы далеки от best practice: таблица не нормализована и осуществлять поиск по ней неудобно.

Попробуем применить другой подход, иерархический, близкий по сути к объектно-ориентированному подходу: в данном случае проектирование БД будет напоминать процесс создания диаграммы класса UML.
Остановимся на атрибутах, свойственных всем типам сущностей: все объекты от мумии фараона до кристалла горного хрусталя можно измерить, сфотографировать и описать словесно. Кроме того, у всех предметов из музейной коллекции есть регистрационный номер, дата регистрации, наименование, описание, тип объекта, статус, категория, и оценка его ценности. На диаграмме эти общие свойства представлены сущностью «Предмет хранения».

«Иерархическая» структура БД каталога музейного фонда
По аналогии с диаграммой классов, родительская сущность «предмет хранения» представлена абстрактным классом, у которого нет своих экземпляров, а на следующем уровне будут представлены конкретные классы (точнее — сущности, если вернуться к терминам логической модели БД). Если же требуется описать разные типы предметов, то нужно создать дочерние сущности для каждого типа: таким образом мы создадим, например, сущности «художественный объект», «природный объект» и «предмет быта».

Между родительской сущностью «предмет хранения» и дочерней сущностью «художественный объект» устанавливается связь «один-к-одному». Надо отметить, это нечастое явление для реляционных баз данных, особенно если учесть что эта связь является идентифицирующей, то есть первичный ключ родительской сущности становится первичным ключом и дочерней сущности. На иллюстрации видно, что один и тот же атрибут «идентификатор предмета хранения» в дочерней сущности является и первичным ключом (отмечено буквой P) и внешним ключом (отмечено буквой F), потому что он прибыл из родительской сущности.
Продолжая описывать разные типы объектов как сущности предметной области и как будущие таблицы базы данных, аналитик будет добавлять в дочерние сущности характеристики, присущие конкретному типу объектов. Например, для художественных объектов можно указать автора, год создания и жанр, а у природных объектов нет создателя, зато для них важно указать автора находки, дату находки, место, экспедицию, из которой привезён этот природный объект. Для предметов быта нужны свои особенные атрибуты, например, принадлежность определённому этносу и культуре.

«Иерархическая» структура БД каталога музейного фонда (сущности для разных типов объектов)
Может оказаться, что с развитием системы потребуется более точно классифицировать объекты дочерней сущности: допустим, художественные объекты могут разделиться на картины и скульптуры. Тогда можно будет создать сущности следующего уровня, также связанные с родительской идентифицирующей связью «один-к-одному» и имеющие свои особые атрибуты: например, для картины можно добавить вид художественной техники, для скульптуры — материал изготовления и т.п.. Природные объекты можно разделить на геологические и биологические, для геологических выделить период и происхождение, для биологических — биологический вид и ареал обитания. Такой способ реализации БД удобен тем, что некоторые виды объектов могут иметь многоуровневую классификацию, реализованную описанным образом, а некоторые — одноуровневую. Нужно отметить что на практике обычно хватает одного-двух дочерних уровней.
Преимущества «иерархической» универсальной структуры БД:

  1. Она даёт возможность с помощью простых JOIN по первичному ключу получить объекты любого типа, состоящие из общих элементов и специфически характерных для определённых объектов
  2. Она позволяет относительно легко добавлять новые типы объектов с новым специфическим набором свойств

Представим, например, что в коллекции музея появился новый вид экспонатов — образцы летающих тарелок из космоса, которые не являются ни природными, ни художественными объектами, ни предметами быта.

В таком случае аналитик, пользуясь абстрактным родительским классом, может добавить и описать виды предметов, которые ранее не были представлены в структуре базы данных.
Пользователь системы сначала добавляет в справочник новый типа объекта «Летающая тарелка» и описывает новые экспонаты, добавляя все стандартные атрибуты для обычных экспонатов: для летающей тарелки можно указать вес, длину, ширину, ценность; ей можно добавить регистрационный номер экспоната. Конечно, если нужно будет снабдить новый вид объекта специфическими атрибутами, то понадобится создать новые таблицы для этих атрибутов. Плюс в том, при создании новой специфической таблицы, существующая модель не будет затронута. Система продолжит работать и может даже не знать, что добавились новые таблицы или поля БД до того момента, пока не будет осуществлён переход на новую версию БД и новые типы объектов появится в системе, отображающей каталог музея.
Как будут выглядеть данные в подобной структуре? На иллюстрации показаны уже не таблицы, как таковые, а скорее результаты некоторых запросов или представления для разных типов объектов. Базовый состав атрибутов из родительской сущности одинаковый у всех, а для каждого типа объектов есть свои собственные специфические атрибуты. Для предметов искусства показаны год создания, вид объекта (картина или скульптура), автор (Васнецов, Шишкин, …), размеры (между прочим, все размеры картин в примере на иллюстрации настоящие). Для геологических объектов мы видим, минералы это или горные породы, в каком процессе и геологическом периоде объект образовался. Для предметов быта можно увидеть, является ли объект посудой, музыкальным инструментом или одеждой, к какому этносу он относится, в каком веке был создан.

Запросы к базе данных можно выполнять, обращаясь не к самой таблице, а к представлению (view), содержащему объекты нужного типа. Результат выполнения запроса будет иметь вид, как на иллюстрации ниже.

Пример данных каталога музейного фонда в «иерархической» БД
Сценарий 3.
Неопределённый состав
сущностей предметной области
В завершение рассмотрим третью группу примеров — ситуации, где аналитик и группа разработки не знают границы предметной области и не могут их очертить при разработке БД.

Пример 1: учёт объектов мониторинга в системе контроля безопасности

Возьмём пример из реальной практики: некая организация проводит мониторинг объектов разного типа для предотвращения нарушений безопасности. На момент старта обновления информационной системы в ней уже реализована возможность мониторинга событий, связанных с определёнными компаниями, физическими лицами, банковскими счетами, и рядом других объектов, обладающих совершенно разными свойствами в реальном мире. Кроме того, в ближайшем будущем в систему планируется добавить новые типы объектов для мониторинга, причём необходимо, чтобы новые типы объектов и их атрибутов можно было добавлять силами пользователя системы. В такой ситуации требуется, чтобы БД вела себя предсказуемо и сохраняла целостность, даже если будет добавлено множество очень отличающихся по свойствам объектов.
Пример 2: учёт объектов городского хозяйства

Тоже реальный пример, с постановкой задачи, похожей на предыдущий случай: при учёте объектов городского хозяйства в АС заказчика уж учитывается несколько сотен типов объектов, и заявлено, что в будущем будут появляться новые типы, со своими атрибутами, однако перечень новых типов заказчику пока неизвестен. Также должна быть возможность дорабатывать модель силами пользователей системы.

Пример 3: итеративное построение БД в Agile проекте

В случае быстрого прототипирования или агрессивно коротких сроков разработки (например, на фазе MVP) команде нужно быстро продемонстрировать работоспособную систему с ограниченным, но жизнеспособным набором возможностей. Причём ни заказчики, ни стейкхолдеры ещё не знают, какие объекты и части предметной области будет нужно охватить в дальнейшем.
Все три приведённых выше примера объединяет одна и та же проблема: отсутствие чётких границ предметной области и вероятность сценария, когда по мере развития системы придётся её существенно менять и расширять.

В этом случае подойдет то, что мы в рамках данной статьи будем называть подобием EAV. Если вам знаком термин EAV (Entity-Attribute-Value), то вы заметите, что изложенное далее похоже на описание его реализации средствами РСУБД. Сходство очевидно, и на этом примере можно хорошо проследить построение связи между объектами БД по принципу «ключ -значение». Такие модели мало отражают специфику сущностей предметной области или их свойств: и объекты и атрибуты носят абстрактный характер.

Универсальная структура БД объектов городского хозяйства (подобие EAV)
При проектировании такой модели стоит начать со справочной части. Как и в случае с финансовой отчётностью из примера выше, сначала нужно создать сущности, которые будут представлять типы объектов и их атрибутов («Тип объекта» и «Атрибуты типа объектов»). Для хранения непосредственно данных будут предназначены сущности «Объект предметной области» и «Значения атрибутов».

Обратите внимание на некоторые особенности модели. Во-первых, добавлена рекурсивная связь для объектов предметной области: это способ поддерживать их иерархию, например, позволяющий добавить сотрудника и потом через ссылку на другую запись этой же таблицы указать, что он является подчинённым другого человека (атрибут «ИД родительского объекта»). Во-вторых, в таблице значений атрибутов созданы поля для разных типов значений (число, текстовая строка, дата и так далее), поскольку очевидно, что разные атрибуты имеют разные типы данных.

Посмотрим на пример данных для такой структуры.

Пример данных БД объектов городского хозяйства
Зелёным цветом выделены ключевые поля, а белым — поля с данными. Обратите внимание, что у каждого атрибута заполнено только одно поле, в соответствии с типом этого атрибута, а поля неподходящих типов атрибутов остаются пустыми. Объект номер 1 — это «Дом номер пять по улице Зелёной» (светло-жёлтым в таблице выделены поля присоединенных с помощью JOIN справочников). В таблице один объект описан с помощью семи записей, соответствующих его свойствам. Объект типа «дом» имеет атрибуты: «улица», «номер дома», «количество этажей», «количество подъездов», «количество квартир», «дата ввода в эксплуатацию», «материал», «фотографии».

Второй объект — скамейка, он относится к другому типу и имеет свой комплект атрибутов: «инвентарный номер», «дата покупки» и так далее. Обратите внимание, что для скамейки два раза указан атрибут материал, с разными идентификаторами атрибутов, потому что скамейка может быть сделана из двух разных материалов: например, стали и дерева. И, наконец, третий тип объекта — «дерево», и у него свой комплект атрибутов: «дата посадки», «фото», «порода».
Такая незамысловатая структура позволит сохранять данные о любых типах объектов с тем комплектом атрибутов, которые указаны для них в справочной части базы данных. А при необходимости можно будет добавить в систему любой новый тип объекта, например, упомянутую выше летающую тарелку, и создать для неё собственные атрибуты: например, «диаметр», «тип топлива», «планета, с которой она прилетела». После этого пользователи смогут добавить записи этого типа объектов в систему для учёта.
Проблемы подхода типа EAV в РСУБД
Предложенный подход имеет некотрые очевидные недостатки. Во-первых, для каждого вида атрибутов объекты указываются независимо, как разные поля БД со своими собственными значениями: например, атрибут «фото» указан для дома, скамейки и для дерева, но ячейки в таблице могут быть заполнены по-разному. В одном случае пользователь мог ввести значение «фото», в другом — «фотография», в третьем «изображение» и так далее. При построении отчёта значения этих полей будут интерпретироваться как разные атрибуты, и пользователь не сможет быстро выбрать все фотографии, например, если они понадобятся ему для создания какого-нибудь иллюстрированного каталога.

Во-вторых, фактически справочные значения указываются как строковые, в результате чего, например, один и тот же материал можно указать разными способами: «кирпич», «кирпичный», «сделан из кирпича», что тоже затрудняет построение выборки и перекладывает ответственность за соблюдение единообразия справочников на пользователя.

Частично справиться с этими проблемами проблемой поможет гибридный подход, описанный далее.
Гибридный подход к проектированию универсальной модели РСУБД
Рассмотрим ещё более универсальный подход к проектированию модели РСУБД, который мы назвали гибридным.

Гибридная структура БД объектов городского хозяйства
Иллюстрация отражает сочетание нескольких подходов к созданию модели РСУБД. Центральная часть этой модели представляет собой модель из предыдущего примера: тип объекта, атрибуты, экземпляры объекта, значения атрибутов. Также добавлены поля начала и окончание действия значения атрибута, для того, чтобы можно было поддерживать версионность значений.

Центральная часть гибридной модели БД повторяет подход типа EAV
Для того, чтобы избежать в данных множества пустых полей для неподходящего типа атрибутов, в нашей модели значения атрибутов разного типа размещены по отдельным маленьким таблицам, чтобы числа хранились с числами, даты с датами, строки со строками, а всякие фотографии и сканы документов, самые тяжёлые объекты — лежали в своей таблице.

Для разного типа значений предусмотрены свои таблицы БД
Кроме того, здесь добавлен ещё один тип атрибутов — «справочное значение». Для них создан универсальный справочник, в который вынесены все справочные значения всех справочников, которые нужны в системе. Здесь могут содержаться возможные значения для марки машины, материала изготовления домов, типа скамеек и так далее. Для возможности поддержки иерархических справочников добавлена рекурсивная связь и идентификатор родительской записи. Значения атрибутов будут храниться в таблице «Значение из справочника», в которой каждое значение атрибута будет представлять собой ссылку на определённую запись универсального справочника.

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

Справочник атрибутов
Напоследок поговорим о реализации связей между объектами. Конечно, рекурсивная связь позволяет создавать иерархическую конструкцию, но проблема в том, что между одними и теми же типами объектов в системе может быть несколько разных типов связей. Например, Вася пошёл работать к своему брату Пете, и Петя стал его начальником. Тогда между двумя экземплярами получается два типа связи: один симметричный («брат — брат»), а другой —иерархический («подчинённый — начальник»). С помощью простой рекурсивной связи такие типы связи указать нельзя. Решается эта проблема тем, что все отношения выносятся в отдельную сущность, что позволяет для любых двух типов объектов указать сколько угодно типов связей, если они требуются в системе. На иллюстрации это вы видите в таблицах «Тип отношения» и «Отношения между типами объектов» (справочная часть) и «Отношения между объектами» (собственно, данные).

Вынос отношений в отдельную сущность для реализации связей между объектами
Подобные гибридные подходы доказали свою работоспособность в целом ряде реальных проектов.
Плюсы и минусы универсальных структур БД
Плюсы

Система приобретает гибкость, позволяющую вносить изменения в модель предметной области, не меняя структуру БД и программный код. В базу данных можно вносить новые типы объектов без ограничений, и АС продолжить функционировать с новыми данными.
Минусы

1. Часть логики данных, которую принято «поручать» базе данных (прежде всего — поддержку целостности), перекладывается с базы данных на совесть разработчика, поскольку на уровне БД не удастся создать ограничения, препятствующие, например, ошибочному присвоению объектам нехарактерных для них атрибутов. Рассмотрим возможную проблему на примере с учётом объектов городского хозяйства. Для дома существует признак «количество этажей», но пользователь может случайно связать признак количества этажей с сущностями, для которых он не несёт смысла, — например, добавить этажность сущности «скамейка». Следить за тем, чтобы ограничить подобные действия, приходиться разработчикам, которые должны предусмотреть уместные ограничения в системе на уровне программного кода, а не структуры БД.
2. Запросы к такой базе данных усложняются из-за появления сложных JOIN, вложенных и рекурсивных запросов. Не все СУБД поддерживают подобные запросы одинаково хорошо, и, как следствие, страдает производительность системы. Кроме того, создание запросов к такой базе данных потребует уровня квалификации, превышающего типичные возможности рядовых аналитиков или бизнес-пользователей, что заметно снизит удобство работы с данными.
Как выбирать подход к
проектированию структуры БД?
  1. Традиционный подход — неуниверсальные (специализированные, конкретные) структуры — хорош там, где предметная область понятна и статична и где не ожидается изменений в составе сущностей атрибутов, по крайней мере, в обозримом будущем.
  2. Универсальные или абстрактные структуры полезны там, где предметная область подвержена турбулентности, где заранее неизвестны её границы, где сущности могут появляться и исчезать, а их атрибутивный состав — меняться.
  3. Можно использовать совмещенный подход, предусмотрев возможность расширения специализированной структуры БД дополнительными объектами, спроектированными в универсальном подходе. Это позволит гибко реагировать на изменение ситуации даже в типовых проектах. Например, как в случае базы предметов хранения в музее: можно было бы создать небольшую универсальную структуру для введения новых типов объектов и их атрибутов.
Заключение
Итак, прочитав эту статью, вы:

1. Научились распознавать ситуации, когда нужно применять универсальную структуру реляционной БД и выбирать подход к её проектированию
2. Поняли различие между универсальной и НЕуниверсальной структурой БД.
3. Познакомились с подходами к проектированию реляционной БД для:

  • Неопределённого состава атрибутов сущностей
  • Сущностей с разным атрибутным составом
  • Неопределённого состава сущностей

Воркшоп Дарьи Колесовой из Яндекса


«От проектирования до эксплуатации:

реляционные БД и SQL-запросы для аналитика

(на примере PostgreSQL)»

8 часов в выходные 17-18 февраля

Ждём начинающих ИТ-специалистов, которые хотят:
  • научиться проектировать физическую модель реляционной БД, наполнять её данными и
  • делать базовые SQL-запросы к ней (операторы SELECT, WHERE, LIKE, ORDER BY, GROUP BY, HAVING, JOIN)
Ваш промокод: SQL50 даст скидку 50%
Полезные ссылки

Больше полезных статей

Автор
Александр Кротов
Аналитик, геолог, кандидат геолого-минералогических наук, преподаватель
  • Из научной сферы в IT перешёл в конце 1990-годов
  • Работал в разных компаниях в роли ведущего бизнес- и системного аналитика
  • Участвовал в реализации большого количества проектов, как в государственном, так и в частном секторе
  • Занимается преподавательской работой
  • Ведёт образовательный Telegram/YouTube канал «Клуб (вне)системных аналитиков»