Зачем использовать отношения «один к одному» при проектировании базы данных?

Мне сложно понять, когда использовать отношение 1 к 1 в дизайне БД или если это когда-либо понадобится.

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

Итак, при разработке схемы базы данных, как вы учитываете отношения «один к одному»? Какие критерии вы используете, чтобы определить, нужен ли он вам, и каковы преимущества его неиспользования?


person chobo    schedule 13.03.2012    source источник
comment
stackoverflow.com/questions/517417/ в значительной степени подводит итог.   -  person Willem van Rumpt    schedule 13.03.2012
comment
Я знаю, что это старый вопрос, но у меня есть много примеров законных отношений 1: 1, для большинства из которых они являются ЕДИНСТВЕННЫМ правильным решением: stackoverflow.com/ questions / 517417 /   -  person Tripartio    schedule 18.01.2016


Ответы (6)


С логической точки зрения соотношение 1: 1 всегда следует объединять в единую таблицу.

С другой стороны, для такого физические > вертикальное разбиение или разбиение строк, особенно если вы знаете, что к одним столбцам будете обращаться чаще или по другому шаблону, чем к другим, например:

  • Возможно, вам понадобится кластер или разделить две таблицы конечных точек отношения 1: 1 по-разному. .
  • Если ваша СУБД позволяет это, вы можете разместить их на разных физических дисках (например, более критичных для производительности на SSD, а другой на дешевом HDD).
  • Вы измерили влияние на кэширование и хотите убедиться, что горячие столбцы хранятся в кеше, а холодные столбцы не загрязняют его.
  • Вам нужно, чтобы поведение параллелизма (например, блокировка) было уже, чем вся строка. Это сильно зависит от СУБД.
  • Вам нужна разная безопасность для разных столбцов, но ваша СУБД не поддерживает разрешения на уровне столбцов.
  • Триггеры обычно привязаны к таблице. Хотя теоретически вы можете иметь только одну таблицу и триггер игнорировать неправильную половину строки, некоторые базы данных могут налагать дополнительные ограничения на то, что триггер может и не может делать. Например, Oracle не позволяет вам изменять так называемую изменяющуюся таблицу из триггера на уровне строки - имея отдельные таблицы, только одна из них может изменяться, поэтому вы все равно можете изменять другую из своего триггера (но есть другие способы решения этой проблемы).

Базы данных очень хорошо манипулируют данными, поэтому я бы не стал разбивать таблицу только для оценки производительности обновления, если вы не выполнили фактические тесты на репрезентативных объемах данных и пришли к выводу, что разница в производительности действительно существует. и достаточно значительный (например, чтобы компенсировать возросшую потребность в СОЕДИНЕНИИ).


С другой стороны, если вы говорите о 1: 0 или 1 (а не об истинном 1: 1), это совершенно другой вопрос, заслуживающий другого ответа ...

См. Также: Когда мне следует использовать отношения "один к одному"?

person Branko Dimitrijevic    schedule 13.03.2012
comment
Из того, что я собрал в ответах, кажется, что 1: 1 следует использовать в основном для оптимизации производительности или безопасности. Мне нравится идея использовать супертип / подтип, но, насколько я понимаю, это считается 1: 0 или 1. - person chobo; 14.03.2012

Разделение обязанностей и абстракция таблиц базы данных.

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

РЕДАКТИРОВАТЬ

Прямо сейчас, если вы хотите иметь запись человека, и у каждого человека будет ровно одна запись адреса, тогда у вас может быть отношение 1 к 1 между таблицей Person и таблицей Address, или у вас может быть просто таблица Person, в которой также есть столбцы для адреса.

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

person bdparrish    schedule 13.03.2012
comment
Если вы добавляете запись в address таблицу без добавления записи в user таблицу, это больше не является отношением 1: 1. - person Branko Dimitrijevic; 13.03.2012
comment
Либо я не понимаю вашего объяснения, либо оно не имеет смысла. - person Willem van Rumpt; 13.03.2012
comment
@BrankoDimitrijevic, исходное объяснение, очевидно, не ясно изложило мою точку зрения. Я имел в виду только, что если вы измените стратегию данных в будущем, чтобы у каждого человека было несколько адресов, тогда все, что вам нужно было бы сделать, это добавить новую запись в таблицу адресов, и теперь у вас есть отношение 1 ко многим между человеком и адресом. . - person bdparrish; 13.03.2012
comment
@bdparrish Да, тезис об эволюции верен. Если ожидается, что текущее соотношение 1: 1 в будущем станет 1: N (или даже просто 1: 0 или 1), тогда предварительное разделение таблицы может быть оправдано. +1 от меня при перепрошивке этот момент. - person Branko Dimitrijevic; 13.03.2012

Что ж, на бумаге нормализованная форма выглядит лучше всего. В реальном мире это обычно компромисс. Большинство известных мне крупных систем идут на компромиссы и не пытаются быть полностью нормализованными.

Попробую привести пример. Если вы находитесь в банковском приложении со счетом в 10 миллионов сберегательных книжек, и обычные транзакции будут просто запросом последнего баланса определенной учетной записи. У вас есть таблица A, в которой хранится только эта информация (номер счета, баланс счета и имя владельца счета).

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

A и B имеют взаимно однозначное сопоставление.

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

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

Наличие всех 43 атрибутов в одной таблице кажется естественным и, вероятно, «естественно медленным» и неприемлемым для простого получения баланса одного счета.

person Daniel Baktiar    schedule 13.03.2012
comment
Вот где я запутался. В вашем примере у вас есть таблица с 43 атрибутами, и вы извлекаете 3 атрибута в новую таблицу для более быстрого запроса. Не могли бы вы написать запрос, который просто выбирает три столбца из большой таблицы? Есть ли разница в производительности, если вы запрашиваете таблицу с 3 атрибутами по сравнению с таблицей 43, но выбираете только три поля? - person chobo; 13.03.2012
comment
Да просто перечитай. В основном это для того, чтобы разместить их на разных устройствах хранения. - person chobo; 13.03.2012
comment
Точно так же вы используете BLOB и CLOB. Вы часто изолируете их в их собственной связанной таблице, чтобы избежать накладных расходов на столбцы, в которых они не задействованы. - person wmorrison365; 13.03.2012
comment
@ wmorrison365 - Предполагая, что у меня есть таблица с изображениями больших двоичных объектов, и я не выбираю их при запросе этой таблицы, все равно будет много накладных расходов из столбца больших двоичных объектов. Или вы имеете в виду обновление и вставку в таблицу с этим типом данных? - person chobo; 13.03.2012

Имеет смысл использовать отношения 1-1 для моделирования объекта в реальном мире. Таким образом, когда в ваш «мир» добавляются новые сущности, они должны иметь отношение только к данным, к которым они относятся (и не более).

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

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

person wmorrison365    schedule 13.03.2012
comment
Реальные отношения 1: 1 - это единый объект в реальном мире. Вы, вероятно, говорите о 1 к 0 или 1. - person Branko Dimitrijevic; 13.03.2012
comment
Я как раз читал о шаблоне подтипа супертипа. Кажется, это неплохое применение для стола один на один. - person chobo; 13.03.2012
comment
@chobo Это не 1: 1, если не существует ровно одного подтипа. - person Branko Dimitrijevic; 13.03.2012
comment
Я просто имел в виду, что если у вас есть сущность A и сущность B, вы можете сгруппировать их в одну таблицу. Но затем появляется объект C, который относится только к элементам данных (столбцам), которые присутствовали бы в объекте B, тогда у него нет другого выбора, кроме как быть связанным со всей сгруппированной таблицей (даже если он не заинтересован в объекте A столбцы). - person wmorrison365; 13.03.2012
comment
@ wmorrison365 Я не уверен, что вы имеете в виду под словом «принадлежащий», но если отношение между C и B истинно 1: 1 и отношение между B и A истинно 1: 1, то отношение между C и A также должны быть 1: 1. Итак, у вас не может быть ни одного из них, не имея всех из них. Это в значительной степени то, что означает быть отдельным объектом. - person Branko Dimitrijevic; 13.03.2012
comment
@BrankoDimitrijevic, что, если отношения между A и B равны 1: 1, а отношения между B и C равны 1: Многие? Теперь у A ДОЛЖНЫ быть отношения 1: Многие с C. - person bdparrish; 13.03.2012
comment
@bdparrish Именно так. Независимо от того, объединены ли A и B или нет, они оба находятся в отношении 1: N к C. Однако на физическом уровне это обычно выполняется с помощью только одного ИНОСТРАННОГО КЛЮЧА (например, от C к B). - person Branko Dimitrijevic; 13.03.2012
comment
LOL, я совсем заблудился :) Итак, пример не супертип / подтип, или супертип / подтип не 1: 1? - person chobo; 13.03.2012
comment
@chobo Оба. Мы не говорили о супертипе / подтипе, а супертип / подтип обычно не 1: 1. Иерархия различающих категорий 1: 1 только в том случае, если существует ровно один подтип. Если существует более одного подтипа, то при создании экземпляра объекта вы вставляете строку в родительскую таблицу и одну из дочерних таблиц. Поскольку вы не вставляли в все дочерние таблицы, это 1 к 0 или 1, а не точно 1 к 1. Недискриминационная иерархия категорий может теоретически быть 1: 1 (если вы всегда вставляете в родительские и все дочерние таблицы), но это в значительной степени нарушает его цель ... - person Branko Dimitrijevic; 13.03.2012
comment
Это запутанный ответ. Представление реального мира выполняется в диаграмме сущность-связь (ER), а не в реляционной модели. Вопрос OP касается отображения из диаграммы ER в реляционную модель, и последняя часто имеет таблицы, которые не отображаются на мировые сущности (например, таблица отношений M-N). Кроме того, ваши рекомендации по нормализации являются общими и не относятся к этому конкретному вопросу. Ответ, получивший наибольшее количество голосов, лучше резюмирует мотивы создания отдельных таблиц для отношения 1: 1: производительность и безопасность. - person Alan Evangelista; 14.11.2018

Часто люди говорят об отношениях 1: 0..1 и называют это отношением 1: 1. На самом деле типичная СУБД в любом случае не может поддерживать буквальное соотношение 1: 1.

Таким образом, я думаю, что здесь будет справедливо обратиться к подклассам, даже если это технически требует отношения 1: 0..1, а не буквальной концепции 1: 1.

1: 0..1 весьма полезен, когда у вас есть поля, которые были бы одинаковыми для нескольких сущностей / таблиц. Например, поля контактной информации, такие как адрес, номер телефона, электронная почта и т. Д., Которые могут быть общими как для сотрудников, так и для клиентов, могут быть разбиты на объект, созданный исключительно для контактной информации.

Таблица контактов будет содержать общую информацию, такую ​​как адрес и номер (а) телефона.

Таким образом, таблица сотрудников содержит информацию о сотрудниках, такую ​​как номер сотрудника, дату найма и так далее. У него также будет ссылка внешнего ключа на таблицу контактов для контактной информации сотрудника.

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

При этом у каждого сотрудника будет контакт, но не у каждого контакта будет сотрудник. Та же концепция применима к клиентам.

person James Marks    schedule 10.11.2016

Вот несколько примеров из прошлых проектов:

  • таблица TestRequests может иметь только один соответствующий отчет. Но в зависимости от характера запроса поля в отчете могут быть совершенно разными.
  • в банковском проекте таблица Entities содержит различные типы сущностей: Funds, RealEstateProperties, Companies. Большинство этих сущностей имеют похожие свойства, но фонды требуют около 120 дополнительных полей, в то время как они представляют только 5% записей.
person Patrick Honorez    schedule 13.03.2012
comment
Оба этих примера не 1: 1, а 1: 0 или 1. - person Branko Dimitrijevic; 13.03.2012
comment
@Branko: это совершенно верно, но тогда я не вижу никакой пользы от настоящего 1: 1. Более того, я не понимаю, как можно обеспечить ссылочную целостность для реального 1: 1! Одна сторона ДОЛЖНА быть сохранена отдельно, прежде чем можно будет проверить другую. - person Patrick Honorez; 14.03.2012
comment
Этот вид двунаправленного внешнего ключа обсуждается здесь. stackoverflow.com/questions/1607916/ - person sam yi; 14.03.2012
comment
@iDevlop Для некоторых случаев использования см. мой ответ. Истинный 1: 1 обычно обеспечивается путем отсрочки ограничений FOREIGN KEY, но это поддерживается не всеми СУБД (особенно MS SQL Server). Его можно до некоторой степени эмулировать, используя разные PK в двух таблицах (путем введения суррогатного PK, если необходимо), затем позволяя одной из дочерних конечных точек FK быть NULL (чтобы прервать цикл вставки), а затем защищая не-NULL от возврата к NULL триггером. Обычно лучше жить с 1: 0..1 и применять 1: 1 на уровне приложения. - person Branko Dimitrijevic; 14.03.2012
comment
@Branko: +1 за ваш ответ. Какая из известных СУБД поддерживает это соотношение 1: 1? - person Patrick Honorez; 14.03.2012
comment
@iDevlop Насколько я знаю, Oracle и PostgreSQL поддерживают отложенные ограничения. Я верю в IBM DB2, MySQL и Interbase / Firebird, но мне придется это перепроверить. - person Branko Dimitrijevic; 14.03.2012