Tabele bez klucza podstawowego

Mam kilka tabel, których jedyne unikalne dane to kolumna uniqueidentifier (Guid). Ponieważ GUID nie są sekwencyjne (i są generowane po stronie klienta, więc nie mogę użyć newsequentialid ()), zrobiłem nie-podstawowy, nie-klastrowy indeks na tym polu ID, zamiast dawać tabel klastrowy klucz podstawowy.

Zastanawiam się, jakie są implikacje wydajności dla tego podejścia. Widziałem, że niektórzy ludzie sugerują, że tabele powinny mieć auto-inkrementacji ("identity") int jako klastrowy klucz podstawowy, nawet jeśli nie ma żadnego znaczenia, ponieważ oznacza to, że sam silnik bazy danych może użyć tej wartości, aby szybko wyszukać wiersz zamiast używać zakładki.

Moja baza danych jest replikowana na kilku serwerach, więc uniknąłem kolumn identity int, ponieważ są trochę Owłosione, aby uzyskać prawo w replikacji.

Jakie są Twoje myśli? Czy tabele powinny mieć podstawowe klucze? A może nie ma żadnych klastrowych indeksów, jeśli jest czy nie ma sensownych kolumn do indeksowania w ten sposób?

Author: Mark Harrison, 2008-08-08

7 answers

Mając do czynienia z indeksami, musisz określić, do czego będzie używana twoja tabela. Jeśli najpierw wstawiasz 1000 wierszy na sekundę i nie wykonujesz żadnych zapytań, to klastrowy indeks jest uderzeniem W wydajność. Jeśli wykonujesz 1000 zapytań na sekundę, Brak Indeksu doprowadzi do bardzo złej wydajności. Najlepszą rzeczą do zrobienia podczas próby dostrojenia zapytań/indeksów jest użycie analizatora planu zapytań i SQL profilera w SQL Server. To pokaże ci, gdzie jesteś uruchomiony w kosztowne skanowanie tabeli lub inne blokery wydajności.

Jeśli chodzi o argument GUID vs ID, w sieci można znaleźć ludzi, którzy przeklinają oba. Zawsze uczono mnie używać GUIDs, chyba że mam naprawdę dobry powód, żeby tego nie robić. Jeff ma dobry post, który mówi o powodach używania GUID: https://blog.codinghorror.com/primary-keys-ids-versus-guids/.

Jak w przypadku większości rzeczy związanych z rozwojem, jeśli chcesz poprawić wydajność, nie ma jednej, jednej właściwej odpowiedzi. To naprawdę zależy od tego, co próbujesz osiągnąć i jak wdrażasz rozwiązanie. Jedyną prawdziwą odpowiedzią jest Testowanie, Testowanie i testowanie ponownie pod kątem wskaźników wydajności, aby upewnić się, że osiągasz swoje cele.

[Edytuj] @Matt, po dalszych badaniach nad dyskusją o GUID/ID natknąłem się na ten post. Jak wspomniałem wcześniej, nie ma prawdziwej dobrej lub złej odpowiedzi. To zależy od twoich konkretnych potrzeb wdrożeniowych. Ale są to dość ważne powody, aby używać GUIDs jako klucz główny:

Na przykład istnieje problem znany jako "hotspot", w którym pewne strony danych w tabeli są w stosunkowo wysokim sporze walutowym. Zasadniczo, to, co się dzieje, to większość ruchu na stole (a tym samym blokada na poziomie strony)występuje na małym obszarze tabeli, pod koniec. Nowe rekordy zawsze trafią do tego hotspotu, ponieważ tożsamość jest generatorem liczb sekwencyjnych. Te wstawki są kłopotliwe, ponieważ wymagają wyjątkowej blokady strony na strona, do której są dodawane (hotspot). Dzięki mechanizmowi blokowania stron wszystkie wkładki są skutecznie serializowane do tabeli. Nevid () z drugiej strony nie cierpi na hotspoty. Wartości generowane za pomocą funkcji Nevid() są sekwencyjne tylko dla krótkich serii wstawek (gdzie funkcja jest wywoływana bardzo szybko, na przykład podczas wstawiania wielowarstwowego), co powoduje, że wstawione wiersze są losowo rozłożone na stronach danych tabeli zamiast wszystkich na końcu-eliminując w ten sposób hotspot z wkładek.

Ponadto, ponieważ wkładki są losowo rozmieszczone, szansa na podział stron jest znacznie zmniejszona. Chociaż strona podzielona tu i tam nie jest tak źle, efekty szybko się sumują. W przypadku tożsamości współczynnik wypełnienia strony jest dość bezużyteczny jako mechanizm strojenia i równie dobrze może być ustawiony na 100% - wiersze nigdy nie zostaną wstawione na żadnej stronie, ale na ostatniej. Dzięki Nevid (), możesz użyć Fill Factor jako narzędzia wspomagającego wydajność. Współczynnik wypełnienia można ustawić na poziomie to przybliża szacowany wzrost wolumenu między odbudowaniami indeksu, a następnie zaplanuje odbudowę w godzinach poza szczytem za pomocą dbcc reindex. To skutecznie opóźnia wydajność odsłon podziałów stron aż do czasów poza szczytem.

Jeśli nawet myślisz możesz potrzebować włączyć replikację dla danej tabeli - równie dobrze możesz uczynić PK uniqueidentifier i oznaczyć pole guid jako ROWGUIDCOL. Replikacja będzie wymagała unikatowego pola guid z tym atrybutem, a to doda jeden, jeśli nie istnieje. Jeśli istnieje odpowiednie pole, to po prostu użyje tego, które tam jest.

Kolejną ogromną zaletą korzystania z GUID dla PKs jest fakt, że wartość jest rzeczywiście gwarantowana unikalna - nie tylko wśród wszystkich wartości generowanych przez ten Serwer, ale wszystkie wartości generowane przez wszystkie komputery-czy to serwer db, serwer WWW, serwer aplikacji lub maszyna kliencka. Prawie każdy współczesny język ma możliwość generowania poprawnego guid teraz - w. NET można użyć System.Guid.NewGuid. Jest to bardzo przydatne szczególnie w przypadku buforowanych zbiorów danych typu master-detail. Nie musisz zatrudniać szalonych tymczasowych programów keying tylko po to, aby powiązać swoje rekordy razem, zanim zostaną one popełnione. Po prostu pobierasz nowy identyfikator Guid z systemu operacyjnego dla stałej wartości klucza każdego nowego rekordu w momencie jego utworzenia.

Http://forums.asp.net/t/264350.aspx

 33
Author: JeremiahClark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Klucz podstawowy służy do trzech celów:

  • wskazuje, że kolumny powinny być unikalne
  • wskazuje, że kolumny nie powinny być null
  • document the intent that this is the unique identifier of the row

Pierwsze dwa mogą być określone na wiele sposobów, jak już to zrobiłeś.

Trzeci powód jest dobry:

  • dla ludzi, aby mogli łatwo zobaczyć Twoje intencje
  • dla komputera, więc program, który może porównać lub w przeciwnym razie proces tabeli może odpytywać bazę danych o klucz podstawowy tabeli.

Klucz podstawowy nie musi być automatycznie zwiększającym się polem liczb, więc powiedziałbym, że dobrym pomysłem jest określenie kolumny guid jako klucza podstawowego.

 7
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 03:04:55

Po prostu wskakuję, bo Matt mnie trochę zwabił.

Musisz zrozumieć, że chociaż klastrowy indeks jest domyślnie umieszczany na głównym kluczu tabeli, to te dwa pojęcia są oddzielne i powinny być rozpatrywane oddzielnie. CIX wskazuje sposób przechowywania danych i odwoływania się do nich przez NCIXs, podczas gdy PK zapewnia unikalność dla każdego wiersza, aby spełnić wymagania logiczne tabeli.

Tabela bez CIX to tylko kupa. Stół bez PK jest często uważany za "nie Stół". Najlepiej jest zrozumieć zarówno koncepcje PK, jak i CIX oddzielnie, aby móc podejmować rozsądne decyzje w projektowaniu baz danych.

Rob

 7
Author: Rob Farley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-05 04:51:00

Nikt nie odpowiedział na pytanie: Jakie są plusy / minusy tabeli bez PK ani klastrowego indeksu. Moim zdaniem, jeśli zoptymalizujesz pod kątem szybszych wstawek (zwłaszcza przyrostowych bulk-insert, np. gdy zbiorczo ładujesz dane do niepustej tabeli), taka tabela: bez klastrowego indeksu, bez ograniczeń, bez kluczy obcych, bez domyślnych i bez klucza podstawowego, w bazie danych z prostym modelem odzyskiwania, jest najlepsza. Teraz, jeśli kiedykolwiek chcesz odpytywać tę tabelę (w przeciwieństwie do skanowania jej w całości), możesz może w razie potrzeby dodać nieklastrowane nie unikalne indeksy, ale ograniczyć je do minimum.

 3
Author: zvolkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-19 18:17:12

Ja też zawsze słyszałem, że automatyczne zwiększanie int jest dobre dla wydajności, nawet jeśli nie używasz go.

 0
Author: Kevin Sheffield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 03:00:36

Klucz podstawowy nie musi być polem autoinkrementacji, w wielu przypadkach oznacza to po prostu komplikowanie struktury tabeli.

Zamiast tego Klucz podstawowy powinien być minimalnym zbiorem atrybutów (zauważ, że większość DBMS zezwala na złożony klucz podstawowy), który jednoznacznie identyfikuje krotkę.

Pod względem technicznym powinno to być pole, od którego każde inne pole w krotce jest w pełni funkcjonalnie zależne. (Jeśli nie jest to może trzeba normalizować).

In praktyka, problemy z wydajnością może oznaczać, że łączysz tabele i używasz pola inkrementacyjnego, ale wydaje mi się, że coś o przedwczesnej optymalizacji jest złe...

 0
Author: Matthew Schinckel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 06:25:50

Ponieważ robisz replikację, twoje są poprawne tożsamości są czymś, co należy unikać. Zrobiłbym z twojego GUID klucz główny, ale niezakłócony, ponieważ nie możesz użyć newsequentialid. To mnie wyróżnia jako Twój najlepszy kurs. Jeśli nie zrobisz z niego PK, ale umieścisz na nim unikalny indeks, prędzej czy później może to spowodować, że osoby utrzymujące system nie zrozumieją prawidłowo relacji FK wprowadzających błędy.

 0
Author: HLGEM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-03 18:20:12