Так, абсолютно є негативні наслідки для використання рядка замість числового типу для Первинного ключа, і тим більше, якщо цей ПК є кластеризованим (що це дійсно у вашому випадку). Однак ступінь, на який ви бачите ефект (и) використання рядкового поля, є функцією: a) скільки рядків у цій таблиці, і b) скільки рядків в інших таблицях є іноземними клавішами до цього ПК. Якщо у вас є лише 10k рядків у цій таблиці та 100k рядків у кількох інших таблицях, які переходять у цю таблицю через це поле, то, можливо, це буде не так помітно. Але ці ефекти, безумовно, стають помітнішими в міру збільшення кількості рядків.
Вам потрібно врахувати, що поля в кластерному індексі переносяться на некластеризовані індекси. Таким чином, ви не просто переглядаєте до 40 байт на рядок, але (40 * деякий чисел) байт. І в будь-яких таблицях FK у вас є ті самі 40 байтів у рядку плюс частіше, ніж не буде кластерного індексу на цьому полі, як воно використовується в JOINs, тому тепер він дійсно подвоюється в будь-яких таблицях, до яких FK ось цей. Якщо хтось схильний думати, що 40 байт * 1 мільйон рядків * 10 примірників цього нічого не турбує, дивіться мою статтю Диск дешевий! ОРЛІ? яка детально описує всі (або принаймні більшість) областей, на які впливає це рішення.
Інша річ, яку слід врахувати, - це те, що фільтрація та сортування рядків, особливо коли не використовується двійкове порівняння (я припускаю, що ви використовуєте за замовчуванням базу даних, яка, як правило, нечутлива до регістру), є набагато менш ефективною (тобто займає більше часу), ніж при використанні INT
/ BIGINT
. Це впливає на всі запити, які фільтрують / приєднуються / сортують у цьому полі.
Отже, використовувати щось на кшталт CHAR(5)
, ймовірно, буде добре для кластеризованого ПК, але в основному, якби це також було визначено COLLATE Latin1_General_100_BIN2
(або щось подібне).
І чи може [CODE]
колись змінюватися значення? Якщо так, то це ще більше причин не використовувати його як ПК (навіть якщо ви встановите значення FK ON UPDATE CASCADE
). Якщо він не може або ніколи не змінить, це добре, але все ж є більш ніж достатньо причин, щоб не використовувати його як кластерну ПК.
Звичайно, питання може бути неправильно сформульоване, оскільки, схоже, у вас в цьому ПК вже є це поле.
Незалежно від того , ваш кращий варіант, безумовно, полягає в використанні в [ID_CODE]
якості кластерного ПК, використовувати це поле у відповідних таблицях як FK, і зберегти [CODE]
як UNIQUE INDEX
(це означає , що це «альтернативний ключ»).
Оновіть
трохи більше інформації на основі цього питання в коментарі до цієї відповіді:
Чи найкращим варіантом [ID_CODE], як ПЕРВІЙНИЙ КЛЮЧ, є використання стовпця [CODE] для пошуку таблиці?
Все це залежить від безлічі факторів, деякі з яких я вже згадував, але перезавантажую:
Первинний ключ - це те, як ідентифікується окремий рядок, незалежно від того, на нього посилаються будь-які іноземні ключі. Як ваша система внутрішньо ідентифікує рядок, пов'язана, але не обов'язково така сама, як, як ваші користувачі ідентифікують себе / цей рядок. Будь-який стовпець NOT NULL з унікальними даними може працювати, але є питання щодо практичності, особливо якщо ПК фактично посилається на будь-які FK. Наприклад, GUID є унікальними, і деякі люди дуже люблять використовувати їх з різних причин, але вони досить погані для кластерних індексів ( NEWSEQUENTIALID
краще, але не ідеально). З іншого боку, GUID-файли є просто відмінними клавішами, які використовує додаток для пошуку рядка, але ПРИЄДНАННЯ все ще робиться за допомогою INT (або подібного) ПК.
Поки ви не говорили нам, як [CODE]
поле вписується в систему з усіх кутів, поза тим, як згадати, що саме так ви шукаєте рядки, але чи це для всіх запитів чи лише деяких? Звідси:
Щодо [CODE]
значення:
- Як воно генерується?
- Це додаткові чи псуедо-випадкові?
- Це рівномірна чи різна довжина?
- Які символи використовуються?
- Якщо ви використовуєте алфавітні символи: це чутливість до регістру чи нечутливість?
- Чи може він колись змінитися після вставки?
Щодо цієї таблиці:
- Чи є інші таблиці FK до цієї таблиці? Або ці поля (
[CODE]
або [ID_CODE]
) використовуються в інших таблицях, навіть якщо явно не є іноземними ключами?
- Якщо
[CODE]
єдине поле використовується для отримання окремих рядків, то для якої мети це [ID_CODE]
поле? Якщо він не використовується, навіщо це в першу чергу (що може залежати від відповіді "Чи може [CODE]
поле колись змінюватися?")?
- Скільки рядків у цій таблиці?
- Якщо інші таблиці посилаються на цю таблицю, то скільки і скільки рядків у кожній з них?
- Які індекси для цієї таблиці?
Це рішення не може бути прийнято виключно з питання "NVARCHAR так чи ні?". Я ще раз скажу, що загалом кажучи, я не вважаю це гарною ідеєю, але, безумовно, є випадки, коли це добре. Враховуючи так мало полів у цій таблиці, мало ймовірно, що є ще якісь, або принаймні не багато, індекси. Таким чином, вам може бути добре в будь-якому випадку мати [CODE]
як індекс кластера. І якщо жодна інша таблиця не посилається на цю таблицю, то, можливо, ви також будете добре, зробивши її ПК. Але якщо інші таблиці посилаються на цю таблицю, то я б вибрав [ID_CODE]
поле як ПК, навіть якщо не кластеризовано.