Вопрос о том, как данные внешнего ключа хранятся в SQL - PullRequest
9 голосов
/ 25 августа 2011

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

Допустим, у меня есть таблица с текстовым столбцом "Фрукты". В этом столбце отображается только одно из четырех значений: Груша, Яблоко, Банан и Клубника. У меня есть миллион строк.

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

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

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

Ответы [ 7 ]

6 голосов
/ 25 августа 2011

Типы данных полей на обеих сторонах отношения внешнего ключа должны быть идентичны.

Если ключевое поле родительской таблицы (скажем) varchar(20), то поля внешнего ключа в зависимомТаблица также должна быть varchar(20).Это означает, что да, вам нужно иметь X миллионов строк «Яблоко» и «Груша» и «Банан», повторяющихся в каждой таблице с внешним ключом, указывающим назад на фруктовый стол.

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

Конечно, вы должны сравнить обе установки.Это всего лишь общие правила, и ваши конкретные требования / настройки могут на самом деле работать быстрее с версией ключа-строки.

5 голосов
/ 25 августа 2011

Это правильно.

Вы должны иметь

table fruits
id   name
1    Pear
2    Apple
3    Banana
4    Strawberry

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

2 голосов
/ 25 августа 2011

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

2 голосов
/ 25 августа 2011

Сначала да, это сэкономит место, потому что int - 4 байта, TINYINT - 1 байт.Во-вторых, поиск по этому полю с помощью TYPE INT будет быстрее, чем по VARCHAR.В дополнение к этому вы можете использовать ENUM, если ваши данные не изменятся в будущем.С enum вы получите тот же, может быть, более быстрый результат, чем со вторичной таблицей, и вы избежите дополнительного объединения.

2 голосов
/ 25 августа 2011

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

Нет, если "Fruit" является ПЕРВИЧНЫМ КЛЮЧОМ таблицы "lookup", поэтому он также должен быть ИНОСТРАННЫМ КЛЮЧОМ в "большой" таблице.

Однако, если вы сделаете небольшой суррогатный ПЕРВИЧНЫЙ КЛЮЧ (например, целое число «id») в таблице «lookup» и затем используете его в качестве FOREIGN KEY в «большой» таблице, вы сэкономите место.

1 голос
/ 25 августа 2011

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

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

0 голосов
/ 25 августа 2011

Я понимаю, что вы не действительно хотите использовать внешние ключи. Ааа, Марк Б только что опубликовал последствия для ФК. Но использование второй таблицы в качестве внешнего «провайдера имен» определенно сэкономит место. Вам понадобится дополнительный индекс на fruit.fruit_id. Этот будет довольно маленьким, и он будет ЦИФРОВЫМ. Быстрее, чем индексы на char или varchar.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...