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 idpola automatycznego przyrostu i użycie go w połączeniu z company_idkluczem 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 IDENTITYkolumna powinna zostać dodana, czy byłby to niepotrzebny narzut?
Jeśli dodasz INT IDENTITYkolumnę 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 IDENTITYkolumny, nie możesz utworzyć PK w tej tabeli. Możesz jednak nadal tworzyć indeks klastrowany na stole, o ile nie skorzystasz z tej UNIQUEopcji. 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 IDkolumny w zapytaniach.
INT IDENTITY kolumna lub Hash z org_pathTrwały Kolumna komputerowej?
Biorąc pod uwagę, że nie będziesz przeglądać wierszy na podstawie org_pathwartoś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 IDENTITYkolumna „ID” jest prawdopodobnie najlepsza.
Kolejność kolumn klucza
Biorąc pod uwagę, że IDkolumna 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ść FILLFACTOR90. 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_pathwartości w obrębie company_idsą unikalne, powinieneś nadal tworzyć wyzwalacz, INSERT, UPDATEaby to wymusić. W Trigger wykonaj IF EXISTSzapytanie, które prawdopodobnie wykonuje a COUNT(*)i GROUP BY company_id, org_path. Jeśli coś zostanie znalezione, wydaj polecenie a, ROLLBACKaby anulować operację DML, a następnie RAISERRORpowiedz, ż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_pathjest, nie polecam używania binarnego sortowania. Ponieważ nie będzie znaków diakrytycznych, to nie chcą skorzystać z równoważności językowych.