Существует ли нормализованная форма для представления нескольких объектов из разных таблиц? - PullRequest
5 голосов
/ 16 января 2010

Для системы, которую я сейчас собираю, выполняются два следующих сценария:

  1. Моя система разрешений является постоянным фаворитом присоединения разрешений к ролям и ролям для пользователей, но с изюминкой: разрешения могут применяться к любому активу на любом уровне, и существует 4 «Уровня», пронумерованных 0 3. Таким образом, таблица назначения ролей состоит из 5 полей: уровень ресурса, идентификатор ресурса, идентификатор роли, идентификатор пользователя и флаг «отключено». Эта система «Tier / ID» также используется при назначении пользователей «домашнему активу».

    К сожалению, побочным эффектом этой системы является то, что в общем случае гораздо проще разрешить эти ссылки на ресурсы в самом приложении, а не в SQL (я знаю, что это можно было бы сделать, но это привело бы к серьезным последствиям). уродливые запросы). Есть ли лучший способ представить такого рода отношения? Является ли это приемлемым способом представления этих отношений?

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

  2. Аналогичная проблема, но другой контекст данных: на самом нижнем уровне устройства могут быть «подключены». Устройствам также разрешается размещать в графическом представлении (например, на карте), а информация об их расположении сохраняется в базе данных. Графические ссылки (также называемые «точками») должны указывать на реальное устройство, но реальное устройство может не указывать на графическую ссылку.

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

    1. Создать серию нормализованных таблиц для представления отдельных устройств и использовать аналогичную систему «тип устройства / идентификатор устройства» для их поиска и сохранить эту информацию в таблице «точек»; для этого по-прежнему потребуется, чтобы приложение выполняло посредническую работу по разрешению этих ссылок на фактические устройства в соответствующих таблицах
    2. Создайте серию нормализованных таблиц и наведите их на таблицу «точек»; это решение, вероятно, не потребует, чтобы приложение разыменовывало данные точек, но потребует, чтобы все таблицы устройств были проверены на наличие любого объекта уровня 3.
    3. Используя таблицу точек в качестве ориентира, добавьте все соответствующие отображаемые данные в каждую соответствующую нормализованную таблицу. Хотя это вообще избавит от необходимости разрешать любые поиски, все равно потребуется сканирование каждой таблицы устройств, а также крайне нетерпимо к любым изменениям в том, как должны храниться данные точек, по сравнению с другими решениями.

    Эта проблема уже решена, и я просто не получил записку? Существует ли стандартная схема решения этой проблемы, или я должен просто предположить, что мне придется разрешить эти ссылки самостоятельно?

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

  1. Сохраните всю информацию о каждом устройстве (в сериализованном массиве или каком-либо подобном механизме) в самой таблице точек. В этом есть очевидная проблема: быть полностью неисследимым и игнорировать нормальную форму
  2. Храните все устройства в одной общей таблице. К сожалению, все эти устройства чрезвычайно различаются по типу данных, которые они предоставляют, а также по способу доступа к ним, и для этого в одной таблице потребуется, когда я в последний раз пытался проработать их на бумаге, как минимум 30 (и, вероятно, больше) столбцов, более половины которых будут нулевыми для каждой строки.

Любые решения запрашиваются и приветствуются, хотя я специально ищу существующие шаблоны и / или нормализованные схемы, которые решают эту проблему, если таковые существуют. Если вы точно знаете, что это правильный ответ, «Нет» будет достаточно, и я буду продолжать использовать прикладной уровень для разрешения этих ссылок. Это еще не было проблемой, я просто предпочитаю знать, что я не прокладываю путь в неправильном направлении, когда кто-то уже решил эту / эти проблемы. Заранее спасибо.

РЕДАКТИРОВАТЬ: разрешения / схема активов

Уровень 0 фактически подразумевается и отсутствует в базе данных, но некоторые вещи зарегистрированы как Уровень 0 (идентификатор актива 0)

Уровень 1:

id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
disabled tinyint(1) unsigned not null,

Уровень 2:

id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier1(id)

Уровень 3:

id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier2(id)

Права доступа:

id int(5) unsigned not null primary key auto_increment,
permission_key varchar(16) not null,
permission_desc varchar(128) not null

Роль:

id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
tier1_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
foreign key (tier1_id) references tier1(id)

Role_Permissions:

role_id int(5) unsigned not null,
permission_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (role_id, permission_id),
foreign key (role_id) references roles(id),
foreign key (permission_id) references permissions(id)

User_Role_Permissions:

tier_id tinyint(1) unsigned not null,
asset_id int(5) unsigned not null,
user_id int(5) unsigned not null,
role_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (tier_id, asset_id, user_id, role_id),
foreign key (user_id) references users(id),
foreign key (role_id) references roles(id)

1 Ответ

4 голосов
/ 16 января 2010

Рассматривали ли вы разделение вашей таблицы разрешений на набор таблиц, каждая из которых применяется к отдельной таблице объектов, например, tier_1_assets и tier_1_permissions, а также tier_2_assets и tier_2_permissions. Это упростит запрос разрешений для уровня активов, но сложнее будет запросить все разрешения пользователя (это компромисс).

Я бы также поставил под сомнение предположение, что реляционная база данных является подходящим носителем для хранения ваших данных. Это действительно может быть, но может и не быть. (PHP может ограничить свободу в этом отношении).

Если ваш набор данных небольшой, почему бы не сохранить его в одном сериализованном файле и иметь небольшой сервер, который хранит его в памяти и предоставляет интерфейс запросов? Я уверен, что есть веские причины, почему нет. (В дополнение к PHP)

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

Множество связей между объектами должно указывать вам, куда поместить ваши ключи и ссылки: один-ко-многим -> (ключ <- внешний ключ); многие ко многим -> (ключ <- таблица ссылок -> ключ); от одного к дополнительному -> (ключ <- внешний ключ). </p>

Я не знаю ни одного паттерна, который бы соответствовал вашей проблеме, как было заявлено. Но я заметил, что большинством общих решений, позволяющих избежать создания другой таблицы, очень сложно управлять очень быстро.

...