Jedną rzeczą do rozważenia jest to, że klucz podstawowy i indeks klastrowany to nie to samo. Klucz podstawowy jest ograniczeniem i dotyczy zasad, według których dane żyją (tj. Integralności danych); nie ma to nic wspólnego z wydajnością / wydajnością. Klucz podstawowy wymaga, aby kolumny klucza były unikalne (w kombinacji) i NIE NULL (indywidualnie). PK jest egzekwowane za pomocą unikalnego indeksu, chociaż może być klastrowany lub nieklastrowany.
Indeks klastrowy to sposób fizycznego (tj. Na dysku) porządkowania danych w tabeli i zajmowania się wydajnością; nie ma to nic wspólnego z integralnością danych. Indeks klastrowany możewymagają, aby kolumny kolumn były unikalne (w kombinacji), ale nie musi. Ponieważ jednak Indeks klastrowy jest fizyczną kolejnością danych, musi jednoznacznie identyfikować każdy wiersz bez względu na wszystko. Jeśli więc nie ustawisz, aby wymagała unikatowości, utworzy własną unikalność poprzez ukrytą 4-bajtową kolumnę „unikatowość”. Ta kolumna jest zawsze dostępna w nie unikatowych indeksach klastrowych, ale nie zajmuje miejsca, gdy pola kluczowe są unikalne (w kombinacji). Aby zobaczyć z pierwszej ręki, jak działa ta kolumna „unikatowy” (zarówno w indeksie klastrowanym, jak i w wpływie na indeksy nieklastrowane), zapoznaj się z tym skryptem testowym, który zamieściłem na skrypcie PasteBin: T-SQL, aby przetestować rozmiar unikalizatora .
Stąd główne pytanie:
czy bardziej efektywne byłoby dodanie id
pola automatycznego przyrostu i użycie go w połączeniu z company_id
kluczem podstawowym, czy też spowodowałoby to niepotrzebne obciążenie
łączy te dwie koncepcje, więc należy je rozwiązać osobno, choć zdecydowanie nakładają się na siebie.
Czy IDENTITY
kolumna powinna zostać dodana, czy byłby to niepotrzebny narzut?
Jeśli dodasz INT IDENTITY
kolumnę i użyjesz jej do utworzenia PK, zakładając, że będzie to PK w klastrach, który doda 4 bajty do każdego wiersza. Ta kolumna jest widoczna i użyteczna w zapytaniach. To mógłby być dodawany do innych tabel jako klucz obcy, chociaż w tym konkretnym przypadku, że nie stanie.
Jeśli nie dodasz INT IDENTITY
kolumny, nie możesz utworzyć PK w tej tabeli. Możesz jednak nadal tworzyć indeks klastrowany na stole, o ile nie skorzystasz z tej UNIQUE
opcji. W takim przypadku SQL Server doda ukrytą kolumnę o nazwie „uniquifier”, która zachowuje się jak opisano powyżej. Ponieważ kolumna jest ukryta, nie można jej używać w zapytaniach ani jako odwołania do kluczy obcych.
Jeśli chodzi o wydajność, opcje te są mniej więcej takie same. Tak, zajmie nieco mniej miejsca zajmując nie unikatowy indeks klastrowy, ponieważ niektóre wiersze (z początkowymi unikatowymi wartościami kluczy) zajmują 0 bajtów, podczas gdy wszystkie wiersze w IDENTITY
/ PK zajmą 4 bajty. Ale nie będzie wystarczającej liczby 0-bajtowych wierszy (szczególnie przy oczekiwanej małej liczbie wierszy), aby kiedykolwiek zauważyć różnicę, nie mówiąc już o przewadze wygody korzystania z ID
kolumny w zapytaniach.
INT IDENTITY kolumna lub Hash z org_path
Trwały Kolumna komputerowej?
Biorąc pod uwagę, że nie będziesz przeglądać wierszy na podstawie org_path
wartości, nie ma sensu dodawanie narzutu w utrwalonej kolumnie obliczeniowej oraz konieczność obliczania tego skrótu w zapytaniach w celu dopasowania go do kolumny obliczonej (to był mój oryginalna sugestia, dostępna tutaj w historii zmian , która była oparta na wstępnym sformułowaniu / szczegółach pytania). W tym konkretnym przypadku INT IDENTITY
kolumna „ID” jest prawdopodobnie najlepsza.
Kolejność kolumn klucza
Biorąc pod uwagę, że ID
kolumna rzadko, jeśli w ogóle, będzie używana w zapytaniach, a biorąc pod uwagę, że dwa główne przypadki użycia to uzyskanie „wszystkich wierszy” lub „wszystkich wierszy dla danego company_id
”, utworzę PK na company_id, id
. A ponieważ oznacza to, że wiersze nie są wstawiane sekwencyjnie, podaję wartość FILLFACTOR
90. Konieczne będzie również regularne utrzymywanie indeksu w celu zmniejszenia fragmentacji.
Drugie Pytanie
czy fakt, że company_id jest kluczem podstawowym w innej tabeli, ma tu jakikolwiek wpływ
Nie.
Wyzwalacz
Ponieważ org_path
wartości w obrębie company_id
są unikalne, powinieneś nadal tworzyć wyzwalacz, INSERT, UPDATE
aby to wymusić. W Trigger wykonaj IF EXISTS
zapytanie, które prawdopodobnie wykonuje a COUNT(*)
i GROUP BY company_id, org_path
. Jeśli coś zostanie znalezione, wydaj polecenie a, ROLLBACK
aby anulować operację DML, a następnie RAISERROR
powiedz, że istnieją duplikaty.
Porównanie
W mojej początkowej odpowiedzi (opartej na oryginalnych sformułowaniach / rzadkich szczegółach pytania i dostępnej tutaj w historii zmian ) zasugerowałem użycie binarnego (tj. _BIN2
) Sortowania. Teraz, gdy mamy już wgląd w to, co dokładnie org_path
jest, nie polecam używania binarnego sortowania. Ponieważ nie będzie znaków diakrytycznych, to nie chcą skorzystać z równoważności językowych.