Каков наилучший способ реализации Полиморфной ассоциации в SQL Server?
У меня есть множество экземпляров, где мне нужно реализовать какую-то Полиморфную Ассоциацию в моей базе данных. Я всегда теряю массу времени, размышляя о всех вариантах снова и снова. Вот 3, о которых я могу думать. Я надеюсь, что для SQL Server существует наилучшая практика.
Вот подход с несколькими столбцами
![Multiple Column approach]()
Здесь нет подхода внешнего ключа
![No Foreign Key Approach]()
И вот подход базовой таблицы
![Base table approach]()
Ответы
Ответ 1
Двумя наиболее распространенными подходами являются Table Per Class (т.е. таблица для базового класса и другая таблица для каждого подкласса, которая содержит дополнительные столбцы, необходимые для описания подкласса) и Table Per Hierarchy (т.е. все столбцы в одной таблице, с один или несколько столбцов, позволяющих распознавать подклассы. Какой лучший подход действительно зависит от особенностей вашего приложения и стратегии доступа к данным.
В первом примере у вас будет таблица за класс, изменив направление FK и удалив дополнительные идентификаторы из родителя. Остальные два являются по существу вариантами таблицы для каждого класса.
Ответ 2
Другим общим именем для этой модели является модель супертипа, в которой есть базовый набор атрибутов, который можно расширить путем присоединения к другому объекту. В книгах Oracle он изучается как логическая модель, так и физическая реализация. Модель без отношений позволила бы данным перерасти в недопустимые состояния и сиротские записи. Я бы решительно обосновал потребности перед тем, как выбрать эту модель. Верхняя модель с отношением, хранящимся в базовом объекте, приведет к ошибкам, а в случае, когда поля были взаимоисключающими, у вас всегда будет нуль. Нижняя диаграмма, в которой ключ применяется в дочернем объекте, устранит нули, но также сделает зависимость мягкой зависимостью и позволит сиротам, если каскадирование не выполняется. Я думаю, что оценка этих характеристик поможет вам выбрать подходящую модель. Я использовал все три в прошлом.
Ответ 3
Для решения подобной задачи я использовал следующее решение:
Много-много основанный дизайн: Несмотря на то, что отношение является 1-много между ObjectN и Something, оно эквивалентно взаимосвязи Many-Many с модификацией PK таблицы отношений.
Сначала я создаю таблицу отношений между ObjectN и Something для каждого объекта, а затем я использую столбец Something_ID в качестве PK.
Это DDL отношения Something-Object1, которое одинаково для Object2 и Object3:
CREATE TABLE Something
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Object1
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Something_Object1
(
Something_ID INT PRIMARY KEY,
Object1_ID INT NOT NULL,
......
FOREIGN KEY (Something_ID) REFERENCES Something(ID),
FOREIGN KEY (Object1_ID) REFERENCES Object1(ID)
)
Более подробные сведения и примеры других возможных вариантов этого билета с несколькими иностранными ключами для одного и того же бизнес-правила
Ответ 4
По моему мнению, ваш первый тип подхода - это лучший способ определить как данные, так и ваши классы, но поскольку ваши основные данные должны быть полезны для ребенка.
Итак, вы можете проверить свое требование и определить базу данных.
Ответ 5
Я использовал то, что, как я полагаю, вы бы назвали подходом базовой таблицы. Например, у меня были таблицы для имен, адресов и буквенных номеров, каждый из которых имеет идентификатор как ПК. Затем у меня был объект основной сущности (entityID) и атрибут linking: attribute (entityKey, attributeType, attributeKey), в котором атрибутKey мог указывать на любую из первых трех таблиц, в зависимости от типа атрибута.
Некоторые преимущества: позволяет как можно больше имен, адресов и phonenumbers для каждого объекта, легко добавлять новые типы атрибутов, экстремальную нормализацию, легко распространять общие атрибуты (то есть идентифицировать дублированных людей), некоторые другие преимущества для бизнеса
Недостатки: довольно сложные запросы для создания простых наборов результатов затрудняли управление (т.е. у меня возникли проблемы с наймом людей с достаточно хорошими отбивчиками T-SQL); производительность является оптимальной для ОЧЕНЬ конкретных случаев использования, а не общих; оптимизация запросов может быть сложной
Прожив эту структуру в течение нескольких лет из гораздо более продолжительной карьеры, я бы не стал ее использовать, если у меня не было таких же странных ограничений бизнес-логики и шаблонов доступа. Для общего использования я настоятельно рекомендую, чтобы ваши типизированные таблицы напрямую ссылались на ваши сущности. То есть Entity (entityID), Name (NameID, EntityID, Name), Телефон (PhoneID, EntityID, Телефон), Электронная почта (EmailID, EntityID, Электронная почта). У вас будет некоторое повторение данных и некоторые общие столбцы, но будет намного проще запрограммировать и оптимизировать.
Ответ 6
Подход 1 лучше всего, но связь между чем-то и object1, object2, object3 должна быть одна к одной.
Я имею в виду, что FK в дочерней (object1, object2, object3) таблице должен быть не единственным уникальным ключом или основным ключом для дочерней таблицы.
object1, object2, object3 может иметь значение Полиморфного объекта.
Ответ 7
Для достижения этой цели нет единой или универсальной передовой практики. Все зависит от типа доступа, который потребуется приложениям.
Моим советом было бы сделать обзор ожидаемого типа доступа к этим таблицам:
- Будете ли вы использовать слой OR, хранимые процедуры или динамический SQL?
- Сколько записей вы ожидаете?
- Каков уровень разницы между различными подклассами? Сколько столбцов?
- Будете ли вы выполнять агрегацию или другие сложные отчеты?
- Будет ли у вас хранилище данных для отчетности или нет?
- Вам часто нужно обрабатывать записи разных подклассов в одной партии?
...
Основываясь на ответах на эти вопросы, мы могли бы разработать подходящее решение.
Одной из дополнительных возможностей хранения свойств, специфичных для подклассов, является использование таблицы с парами Имя/значение. Этот подход может быть особенно полезен, если существует большое количество различных подклассов или когда конкретные поля в подклассах используются редко.
Ответ 8
Я использовал первый подход. Под экстремальными нагрузками таблица "Что-то" становится узким местом.
Я принял подход к созданию шаблона DDL для моих разных объектов с добавлением атрибутных спецификаций к концу определения таблицы.
На уровне БД, если я действительно должен представлять свои разные классы в качестве набора записей "Что-то", тогда я помещаю представление поверх них
SELECT "Something" fields FROM object1
UNION ALL
SELECT "Something" fields FROM object2
UNION ALL
SELECT "Something" fields FROM object3
Задача заключается в том, как вы назначаете первичный ключ, не вызывающий конфликта, учитывая, что у вас есть три независимых объекта. Обычно люди используют UUID/GUID, однако в моем случае ключ был 64-битным целым числом, сгенерированным в приложении на основе времени и машины, чтобы избежать столкновений.
Если вы примете такой подход, вы избежите проблемы с объектом "Что-то", вызывающим блокировку/блокировку.
Если вы хотите изменить объект "Что-то", тогда это может быть неудобно, теперь у вас есть три независимых объекта, все из которых потребуют изменения их структуры.
Итак, суммируем. В большинстве случаев вариант One отлично работает, но при тяжелой нагрузке вы можете наблюдать блокировку блокировки, которая требует разделения конструкции.
Ответ 9
Подход 1 с несколькими столбцами внешних ключей является лучшим. Поскольку вы можете иметь предварительно определенные соединения с другими таблицами
И это облегчает сценарии для выбора, вставки и обновления данных.