TL; DR:
Я хочу использовать нереляционный дизайн для хранения дерева узлов в самоссылающейся таблице, потому что нам никогда не потребуется реляционно выбирать подмножества данных. Это позволяет использовать чрезвычайно простые рекурсивные функции хранения и поиска.
Коллега хочет использовать реляционный дизайн для хранения каждого конкретного поля объекта - я полагаю, потому что он считает, что реляционный просто всегда лучше. (у него нет особых причин) Это потребовало бы большего количества таблиц и более сложных функций хранения и извлечения, и я не думаю, что это могло бы принести нам какую-либо пользу.
Есть ли какие-либо конкретные преимущества или недостатки любого из методов проектирования?
Как деревья обычно хранятся в базах данных? Самостоятельные ссылки?
Существуют ли какие-либо известные примеры деревьев данных, хранящихся в базах данных, которые могут совпадать с задачей, которую мы пытаемся решить?
На работе мы используем сложную структуру для описания объекта, к сожалению, я не могу поделиться точной структурой из-за ограничений работы, но я приведу эквивалентный пример структуры и объясню ее особенности.
Структура может быть представлена в формате json, но на самом деле соответствует более жесткому синтаксическому ограничению.
В структуре есть четыре вида сущностей:
- узел верхнего уровня
- Этот узел является объектом json, и он должен быть объектом json верхнего уровня
- Этот узел должен содержать ровно 4 атрибута (метаинформация от 1 до 4)
- Этот узел должен содержать ровно 1 «главный» контейнерный узел
- контейнерные узлы
- Это объекты json, которые содержат другие контейнеры и узоры шаблонов
- Должен содержать ровно 1 атрибут с именем container_attribute
- Может содержать любое количество других контейнеров и шаблонов
- узорные узлы
- Это объекты json, которые содержат ровно 3 атрибута
- Шаблон - это технически контейнер
- Может не содержать ничего
- атрибутивные узлы
- Это просто строковые объекты json
Контейнер верхнего уровня всегда является объектом json, который содержит 4 атрибута и ровно 1 контейнер с именем 'main_container'
Все контейнеры должны содержать один атрибут с именем container_attribute.
Все шаблоны должны содержать ровно три атрибута
Пример структуры в json выглядит следующим образом:
{
"top_level_node": {
"meta_info_1": "meta_info_keyword1",
"meta_info_2": "meta_info_keyword2",
"meta_info_3": "meta_info_keyword3",
"meta_info_4": "unique string of data",
"main_container": {
"container_attribute": "container_attribute_keyword",
"sub_container_1": {
"container_attribute": "container_attribute_keyword",
"pattern_1": {
"pattern_property_1": "pattern_property_1_keyword",
"pattern_property_2": "pattern_property_2_keyword",
"pattern_property_3": "unique string of data"
},
"pattern_2": {
"pattern_property_1": "pattern_property_1_keyword",
"pattern_property_2": "pattern_property_2_keyword",
"pattern_property_3": "unique string of data"
}
},
"pattern_3": {
"pattern_property_1": "pattern_property_1_keyword",
"pattern_property_2": "pattern_property_2_keyword",
"pattern_property_3": "unique string of data"
}
}
}
}
Мы хотим сохранить эту структуру в нашей внутренней офисной базе данных, и я предлагаю использовать три таблицы: одну для хранения всех объектов json в самоссылающейся таблице и одну для хранения всех строк json в таблице, которая ссылается на json таблица объектов, а затем третья таблица, чтобы связать контейнеры верхнего уровня с именем объекта.
Схема будет выглядеть примерно так:
Где таблица attibutes будет использоваться для хранения всего, что является строкой json со ссылками на идентификатор родительского контейнера:
CREATE TABLE attributes (
id int DEFAULT nextval('attributes_id_seq'::text),
name varchar(255),
container_id int,
type int,
value_type int,
value varchar(255)
);
Таблица контейнеров будет использоваться для хранения всех контейнеров в самоссылающейся таблице для создания структуры дерева:
CREATE TABLE containers (
id int DEFAULT nextval('containers_id_seq'::text),
parent_container_id int
);
А затем один список имен объектов, которые указывают на идентификатор контейнера верхнего уровня для объекта:
CREATE TABLE object_names (
id int DEFAULT nextval('object_names_id_seq'::text),
name varchar(255),
container_id int
);
Приятной особенностью вышеупомянутой структуры является то, что она делает действительно простую рекурсивную функцию для итерации дерева и сохранения атрибутов и контейнеров.
Недостатком является то, что он не является реляционным и поэтому не помогает выполнять сложные реляционные запросы для получения наборов информации.
Причина, по которой я говорю, что мы должны использовать это, состоит в том, что у нас нет абсолютно никакой причины выбирать части этих объектов реляционным способом, данные по каждому объекту полезны только в контексте этого объекта, и у нас нет никаких ситуаций где нам нужно будет выбрать эти данные по любой причине, кроме перестройки объекта.
Однако мой коллега говорит, что мы должны использовать дизайн реляционной базы данных для его хранения, и что каждый из атрибутов «ключевого слова» должен иметь свою собственную таблицу (таблица ключевых слов контейнера, 3 таблицы ключевых слов шаблона, 4 таблицы ключевых слов верхнего уровня ).
В результате хранение этих объектов в предлагаемом реляционном дизайне становится значительно более сложным и требует много дополнительных таблиц.
Обратите внимание, что скорость / эффективность запроса не является проблемой, поскольку этот объект / база данных предназначен для внутреннего использования в целях, которые вообще не зависят от времени. В конечном итоге все, что мы делаем с этим, - это создание новых «объектов» и их сохранение, а затем запрос к базе данных для перестройки всех объектов.
Если нет никакой пользы от проектирования реляционной базы данных, то есть ли причина использовать его над чем-то, что допускает такой простой API хранения / поиска?
Есть ли какие-либо существенные проблемы с моей предложенной схемой?