Как правило, строковые (или varchar) поля используются в качестве полей соединения? - PullRequest
1 голос
/ 12 октября 2010

У нас есть две таблицы.Первый содержит поле имени (varchar).Второй содержит поле, которое ссылается на поле имени из первой таблицы.Этот внешний ключ во второй таблице будет повторяться для каждой строки, связанной с этим именем.Как правило, не рекомендуется использовать поле varchar / string в качестве соединения между двумя таблицами?Когда лучше всего использовать строковое поле в качестве поля соединения?

Ответы [ 8 ]

9 голосов
/ 12 октября 2010

Конечно, можно использовать varchar в качестве ключевого поля (или просто что-то, к чему можно присоединиться). Основные проблемы с ним связаны с тем, что вы обычно храните в поле varchar; изменяемые данные. Строго говоря, не рекомендуется менять ключевые поля. Имя человека, номер телефона, даже его SSN могут измениться. Однако сотрудник с внутренним идентификатором 3 всегда будет идентификатором 3, даже если есть два Джона Смита.

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

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

6 голосов
/ 12 октября 2010

Как правило, не рекомендуется использовать поле varchar / string в качестве соединения между двумя таблицами?

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

Когда наилучший случай, когда строковое поле может использоваться в качестве поля соединения?

Зависит от базы данных из-за битов, выделенных для типа данных, нообычно VARCHAR (4) или меньше занимает столько же места (меньше, чем меньшее количество символов), чем INT.

3 голосов
/ 12 октября 2010

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

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

1 голос
/ 12 октября 2010

Иногда объединение происходит в полях, которые не являются «полями объединения», потому что это просто природа запроса (например, большинство способов идентификации записей, которые являются дубликатами в определенном столбце). Если требуемый запрос относится к этим значениям, то это будет соединение, конец истории.

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

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

Обычные запросы могут быть такими, что использование varchar становится более производительным даже без хеш-индексов. Классическим примером является хранение фрагментов текста для многоязычного веб-сайта. Каждый такой фрагмент текста будет иметь определенный languageID, относящийся к языку, на котором он находится. Однако получение другой информации об этом языке (его название и т. Д.) Редко требуется; гораздо чаще нужно либо фильтровать по коду RFC 5646, либо выяснить, что это за код RFC 6546. Если мы используем числовой идентификатор, то для получения этого кода нам потребуется объединиться для обоих типов запросов. Если мы используем код в качестве идентификатора, то наиболее распространенные запросы, связанные с языком, вообще не нужно будут искать в языковой таблице. Большинству запросов, которые заботятся о деталях языка, также не требуется выполнять какое-либо соединение; Практически единственный раз, когда ключ будет использоваться в качестве внешнего ключа, заключается в поддержании ссылочной целостности при обновлении и вставке текста или при удалении языков. Следовательно, хотя объединение менее эффективно, когда оно используется, система в целом будет более эффективной, если использовать меньше объединений.

1 голос
/ 12 октября 2010

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

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

1 голос
/ 12 октября 2010

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

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

0 голосов
/ 12 октября 2010

Естественные первичные ключи, такие как почтовый индекс, номер телефона, адрес электронной почты или имя пользователя, по определению - строки.Они уникальны и относительно коротки.

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

0 голосов
/ 12 октября 2010

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

Ничто не имеет повторяющихся имен?

Я использовал строковое поле в качестве соединения при использовании идентификаторов GUID или одногоидентификаторы символов или когда я знаю, что строка является естественным ключом (хотя я почти всегда предпочитаю суррогат)

...