Да, безусловно, есть отрицательные последствия использования строки вместо числового типа для первичного ключа, и даже более того, если этот PK является кластеризованным (что в действительности имеет место в вашем случае). Тем не менее, степень, в которой вы видите эффект (ы) использования строкового поля, является функцией от a) сколько строк в этой таблице и b) сколько строк в других таблицах имеют внешний ключ к этому PK. Если у вас есть только 10 тыс. Строк в этой таблице и 100 тыс. Строк в нескольких других таблицах, которые передаются в эту таблицу через это поле, то, возможно, это будет не так заметно. Но эти эффекты, безусловно, становятся более заметными по мере увеличения числа строк.
Необходимо учитывать, что поля в кластеризованном индексе переносятся в некластеризованные индексы. Таким образом, вы смотрите не только до 40 байтов на строку, но и (40 * some_number) байтов. И в любых таблицах FK у вас есть те же 40 байтов в строке, и чаще всего в этом поле будет некластеризованный индекс, так как он используется в JOIN, поэтому теперь он действительно удваивается в любых таблицах, для которых FK используется. вот этот. Если кто-то склонен думать, что 40 байтов * 1 миллион строк * 10 копий этого документа не о чем беспокоиться, см. Мою статью « Диск дешев»! ORLY? которая подробно описывает все (или, по крайней мере, большинство) областей, на которые повлияло это решение.
Еще одна вещь, которую следует учитывать, это то, что фильтрация и сортировка по строкам, особенно когда не используется двоичное сопоставление (я предполагаю, что вы используете базу данных по умолчанию, которая обычно нечувствительна к регистру), гораздо менее эффективна (т. Е. Занимает больше времени), чем при использовании INT
/ BIGINT
. Это влияет на все запросы, которые фильтруют / объединяют / сортируют в этом поле.
Следовательно, использование чего-то подобного CHAR(5)
, вероятно, будет хорошо для кластерного PK, но в основном, если оно также было определено с COLLATE Latin1_General_100_BIN2
(или что-то подобное).
И может ли ценность [CODE]
когда-либо измениться? Если да, то это еще одна причина не использовать его в качестве PK (даже если вы установили FK на ON UPDATE CASCADE
). Если он не может или никогда не изменится, это нормально, но все же есть более чем достаточно причин, чтобы не использовать его в качестве кластерного ПК.
Конечно, вопрос может быть неправильно сформулирован, поскольку кажется, что у вас уже есть это поле в вашем ПК.
Независимо от этого, наилучшим вариантом, безусловно, является использование [ID_CODE]
в качестве кластерного PK, использование этого поля в связанных таблицах как FK и сохранение его [CODE]
как UNIQUE INDEX
(что означает, что это «альтернативный ключ»).
Обновление
Немного больше информации на основе этого вопроса в комментарии к этому ответу:
Является ли [ID_CODE], как PRIMARY KEY, лучшим вариантом, если я использую столбец [CODE] для просмотра таблицы?
Все это зависит от множества факторов, некоторые из которых я уже упоминал, но повторю:
Первичный ключ - это способ идентификации отдельной строки независимо от того, на нее ссылаются какие-либо внешние ключи. То, как ваша система внутренне идентифицирует строку, связано, но не обязательно, с тем, как ваши пользователи идентифицируют себя / эту строку. Любой столбец NOT NULL с уникальными данными может работать, но есть вопросы практичности, которые следует учитывать, особенно если на PK на самом деле ссылаются какие-либо FK. Например, GUID являются уникальными, и некоторым людям действительно нравится использовать их по разным причинам, но они довольно плохи для кластерных индексов ( NEWSEQUENTIALID
лучше, но не идеально). С другой стороны, GUID просто хороши как альтернативные ключи и используются приложением для поиска строки, но JOIN все еще выполняется с использованием INT (или подобного) PK.
До сих пор вы не сказали нам, как [CODE]
поле вписывается в систему со всех сторон, за исключением упоминания о том, что именно так вы просматриваете строки, но это для всех запросов или только для некоторых? Следовательно:
Это решение не может быть принято исключительно по вопросу «NVARCHAR да или нет?». Я снова скажу, что, вообще говоря, я не считаю, что это хорошая идея, но бывают случаи, когда это хорошо. Учитывая, что в этой таблице так мало полей, маловероятно, что индексов будет больше или, по крайней мере, не так много. Таким образом, вы могли бы быть хорошо в любом случае иметь [CODE]
в качестве кластерного индекса. И если никакие другие таблицы не ссылаются на эту таблицу, то вы также можете сделать ее PK. Но если другие таблицы ссылаются на эту таблицу, я бы выбрал [ID_CODE]
поле в качестве PK, даже если не кластеризован.