SQL от одного к одному независимо от одной таблицы

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

User

[Id] INT IDENTITY NOT NULL,
[Name] NVARCHAR(MAX) NOT NULL,
[Email] VNARCHAR(2034) NOT NULL

UserSettings

[SettingA],
[SettingB],
[SettingC]

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

Ответ 1

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

Итак, представьте таблицу продуктов. Существует цена продажи и, возможно, другая цена, которая использовалась только для расчета и оценки. Разве было бы неплохо иметь две таблицы, одну для реальных ценностей и одну для этапа планирования? Поэтому программист никогда не спутает две цены. Или возьмите логистические настройки для продукта. Вы хотите вставить в таблицу продуктов, но со всеми этими атрибутами логистики в нем, вам нужно установить некоторые из них? Если бы это были две таблицы, вы бы вставляли их в таблицу продуктов, а другой программист, ответственный за логистические данные, заботился бы о логистической таблице. Больше беспорядка.

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

Последний пункт - права доступа. С помощью отдельных таблиц вы можете предоставить различные права в главной таблице продукта и в таблице логистики продукта.

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

РЕДАКТИРОВАТЬ: Я беру совет Майка Шеррилла и (надеюсь) прояснить вопрос о нормализации.

Нормализация в основном заключается в том, чтобы избежать избыточности и связанной с этим непротиворечивости. Решение о том, хранить ли данные только в одной таблице или более связанных таблицах 1:1, не имеет никакого отношения к этому. Вы можете разделить таблицу пользователя в одной таблице на личную информацию, такую ​​как имя и фамилию, а другое - на его школу, выпуск и работу. Обе таблицы останутся в нормальной форме в качестве исходной таблицы, потому что нет данных, более или менее избыточных, чем раньше. Единственный столбец, используемый дважды, будет идентификатором пользователя, но это не избыточно, потому что в обеих таблицах необходимо идентифицировать запись.

Итак, спрашивайте: "Считается правильным, чтобы нормализовать настройки в отдельной таблице?" это недействительный вопрос, потому что вы ничего не нормализуете, помещая данные в отдельную таблицу, связанную с 1:1.

Ответ 2

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

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

Таблица соединений может быть весьма полезна. Например, он может содержать эффективные и конечные даты установки.

Однако это предполагает, что настройки "похожи" друг на друга, в смысле SQL. Если настройки различны, например:

  • Предпочтительное местоположение как широта/долгота
  • Предпочтительное время суток для получения электронной почты.
  • Флаг, исключаемый из определенных контактов

Затем при хранении данных в таблице возникает проблема с типом данных. Итак, ответ "это зависит". Большая часть ответа зависит от того, как выглядят настройки, как они будут использоваться, и типа ограничений на них.

Ответ 3

Разделение таблиц на отдельные таблицы с отношениями 1:1 между ними обычно не практикуется, потому что:

Если отношение действительно 1:1, то принудительное выполнение целостности сводится к тому, что "вставки выполняются во всех соответствующих таблицах или вообще отсутствуют". Для этого на стороне сервера требуются системы, которые поддерживают проверку отложенных ограничений, и AFAIK, что является признаком довольно высокопроизводительных систем. Поэтому во многих случаях принудительное исполнение 1:1 переносится на сторону приложения, и этот подход имеет свои очевидные недостатки.

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

(Я также предлагаю вам внимательно прочитать дискуссию между Thorsten/Mike. Вы использовали слово "нормализация", но нормализация имеет очень мало общего с вашим сценарием - за исключением случаев, когда вы рассматриваете 6NF, что, я думаю, маловероятно).

Ответ 4

Вы все не правы :) Шучу.

При очень высокой загрузке, сильно обновленной системе с большим объемом, разделение таблицы на 1:1 помогает оптимизировать ввод-вывод.

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

Но такого типа оптимизации обычно не бывает, пока у вас не появятся сотни миллионов строк и огромный параллелизм чтения/записи

Ответ 5

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

UserSettings

[Settings_ID]
[User_ID]
[Settings]

Фактически, можно было бы сделать тот же аргумент для поля [Email].