Варто враховувати, що первинний ключ та кластерний індекс - це не одне і те ж. Первинний ключ - це обмеження і стосується правил, за якими дані живуть (тобто цілісність даних); це не має нічого спільного з ефективністю / продуктивністю. Первинний ключ вимагає, щоб стовпці ключів були унікальними (у поєднанні) та НЕ NULL (окремо). PK застосовується за допомогою унікального індексу, хоча він може бути кластерним або не кластеризованим.
Кластерний індекс - це засіб фізичного (тобто на диску) впорядкування даних у таблиці та стосується продуктивності; це не має нічого спільного з цілісністю даних. Кластерний індекс можевимагають, щоб стовпець ключів був унікальним (у поєднанні), але цього не потрібно. Однак, оскільки кластерний індекс - це фізичний порядок даних, він повинен однозначно ідентифікувати кожен рядок незалежно від того. Отже, якщо ви не встановите його для необхідності унікальності, він створить свою власну унікальність за допомогою прихованого 4-байтового стовпця "Унікалізатор". Цей стовпець завжди є в не унікальних кластерних індексах, але він не займає місця, коли ключові поля є унікальними (у поєднанні). Щоб побачити з перших рук, як працює цей стовпчик "Унікатор" (як у кластерному індексі, так і вплив на некластеризовані індекси), будь ласка, ознайомтеся з цим тестовим сценарієм, який я розмістив у сценарії PasteBin: T-SQL, щоб перевірити розмір Uniquifier .
Отже, головне питання:
чи було б ефективнішим додати поле з автоматичним збільшенням idі використовувати це разом із company_idосновним ключем, чи додасть це зайві накладні витрати
це поєднання цих двох понять, тому їх потрібно вирішувати окремо, хоча, безумовно, є певне збіг.
Чи IDENTITYслід додати стовпець або це буде зайвим накладними?
Якщо ви додаєте INT IDENTITYстовпець і використовуєте його для створення ПК, припускаючи, що це буде ПК із кластером, що додає 4 байти в кожен рядок. Цей стовпець видимий і корисний для запитів. Він може бути доданий до інших таблиць як зовнішній ключ, хоча в цьому конкретному випадку цього не відбудеться.
Якщо ви не додаєте INT IDENTITYстовпець, ви не можете створити ПК у цій таблиці. Однак ви все одно можете створити кластерний індекс на столі до тих пір, поки не будете використані UNIQUEпараметри. У цьому випадку SQL Server додасть прихований стовпець під назвою "Уніфікатор", який веде себе як описано вище. Оскільки стовпець прихований, його не можна використовувати в запитах або як посилання на іноземні ключі.
Що стосується ефективності, ці варіанти приблизно однакові. Так, місця буде зайнято трохи менше, якщо не унікальний кластерний індекс через деякі рядки (ті, які мають початкові унікальні значення ключа) займає 0 байт, а всі рядки в IDENTITY/ PK займуть 4 байти. Але не буде достатньо рядків з 0 байтами (особливо, якщо очікується невелика кількість рядків), щоб коли-небудь помітити різницю, не кажучи вже про те, щоб виважити зручність можливості використання IDстовпця в запитах.
Стовпець ІД ІДЕНТИМЕНТНОСТІ або стовпчик персистованих org_pathобчислених стовпців?
Зважаючи на те, що ви не будете шукати рядки на основі org_pathзначень, то не має сенсу додавати накладні дані Персистового обчисленого стовпця плюс потрібно обчислювати цей хеш у запитах, щоб відповідати обчисленій колонці (це був мій оригінальна пропозиція, наявна в історії оновлень тут , яка базувалася на початковій редакції / деталі запитання). У цьому конкретному випадку INT IDENTITYстовпець "Ідентифікатор", мабуть, найкращий.
Замовлення ключових стовпців
З огляду на те, що IDстовпець рідко, якщо і колись, буде використовуватися в запитах, і враховуючи, що два основні випадки використання - це отримати або "всі рядки", або "всі рядки для заданої company_id", я б створив ПК на company_id, id. А оскільки це означає, що рядки не вставляються послідовно, я б вказав FILLFACTOR90. Також вам потрібно буде забезпечити регулярне обслуговування індексу, щоб зменшити фрагментацію.
Друге питання
чи впливає той факт, що company_id є первинним ключем в іншій таблиці
Ні.
Тригер
Оскільки org_pathзначення в a company_idє унікальними, ви все одно повинні створити тригер INSERT, UPDATEдля його виконання. У тригері зробіть IF EXISTSзапит, який, ймовірно, робить а COUNT(*)і GROUP BY company_id, org_path. Якщо що-небудь знайдено, ROLLBACKвидаліть, щоб скасувати операцію DML, а потім RAISERRORсказати, що є дублікати.
Збірка
У моїй початковій відповіді (грунтуючись на оригінальній формулюванні / розрізнені деталі запитання та доступні в історії редагувань тут ), я запропонував можливо скористатися бінарним (тобто _BIN2) зіставленням. Тепер, коли ми маємо уявлення про те, що саме org_pathє, я б не рекомендував використовувати бінарний Collation. Так будуть діакритичні знаки, ви дійсно хочете використовувати лінгвістичні еквівалентності.