2008-08-08 11 views
38

Mam kilka tabel, których jedynymi unikalnymi danymi są kolumny uniqueidentifier (a Guid). Ponieważ guidy są niesekwencyjne (i generowane po stronie klienta, więc nie można używać newsequentialid()), utworzyłem indeks niebędący podstawowym, nieklastrowym na tym polu identyfikatora, zamiast udostępniać tabele jako klastrowany element główny klawisz.Tabele bez klucza podstawowego

Zastanawiam się, jakie są konsekwencje dla tego podejścia. Zauważyłem, że niektórzy sugerują, że tabele powinny mieć auto-inkrementujące ("identity") int jako klastrowany klucz podstawowy, nawet jeśli nie ma to żadnego znaczenia, ponieważ oznacza to, że silnik bazy danych sam może szybko użyć tej wartości szukaj w rzędzie zamiast używać zakładki.

Moja baza danych jest replikowana na wielu serwerach, więc wycofałem się z kolumn int tożsamości, ponieważ są trochę owłosione, aby uzyskać właściwą replikację.

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

+0

Od kiedy wykonujecie replikację, wasze są to poprawne tożsamości. Uczyniłbym twój GUID kluczem podstawowym, ale nieklastrowany, ponieważ nie możesz użyć newsequentialid. To utwierdza mnie w najlepszym kursie. Jeśli nie stworzysz PK, ale umieścisz na nim unikalny indeks, prędzej czy później może to spowodować, że osoby, które utrzymują system, nie będą poprawnie rozumieć relacji FK, wprowadzając błędy. – HLGEM

Odpowiedz

32

Podczas pracy z indeksami musisz określić, do czego będzie używany Twój stół. Jeśli głównie wstawiasz 1000 wierszy na sekundę i nie wykonujesz żadnych zapytań, indeks klastrowy jest trafieniem do wydajności. Jeśli robisz 1000 zapytań na sekundę, to brak indeksu spowoduje bardzo złą wydajność. Najlepszą rzeczą do zrobienia podczas próby dostrojenia zapytań/indeksów jest użycie Query Plan Analyzer i SQL Profiler w SQL Server. Spowoduje to wyświetlenie miejsca, w którym wykonywane są kosztowne skanowanie tabeli lub inne blokery wydajności.

Jeśli chodzi o argument GUID i ID, można znaleźć osoby online, które przeklinają za pomocą obu. Zawsze uczono mnie używać GUID, chyba że mam naprawdę dobry powód, aby tego nie robić. Jeff ma dobry post, który mówi o powodach używania GUID: http://www.codinghorror.com/blog/archives/000817.html.

Podobnie jak w przypadku większości produktów związanych z rozwojem, jeśli chcesz poprawić wydajność, nie ma jednej, jednej prawidłowej odpowiedzi. To naprawdę zależy od tego, co próbujesz osiągnąć i jak wdrażasz to rozwiązanie. Jedyną prawdziwą odpowiedzią jest testowanie, testowanie i testowanie ponownie w oparciu o wskaźniki wydajności, aby upewnić się, że osiągasz swoje cele.

[Edytuj] @Matt, po przeprowadzeniu kilku badań w debacie GUID/ID natknąłem się na ten post. Tak jak wspomniałem wcześniej, nie ma prawdziwej odpowiedzi słusznej lub błędnej. To zależy od konkretnych potrzeb związanych z wdrażaniem. Są to jednak pewne uzasadnione powody używania identyfikatorów GUID jako klucza podstawowego:

Na przykład występuje problem znany jako "hotspot", w którym niektóre strony danych w tabeli znajdują się pod względnie wysokim wpływem na waluty. Zasadniczo, co się dzieje, większość ruchu w tabeli (a tym samym blokady na poziomie strony) pojawia się na niewielkim obszarze stołu, pod koniec. Nowe rekordy zawsze będą przechodzić do tego hotspotu, ponieważ TOŻSAMOŚĆ jest generatorem liczb sekwencyjnych. Te wstawki są kłopotliwe, ponieważ wymagają zablokowania strony na stronie, do której są dodawane (hotspot). To skutecznie serializuje wszystkie wkładki do stołu dzięki mechanizmowi blokowania stron. Natomiast NewID() nie ma hotspotów. Wartości generowane za pomocą funkcji NewID() są tylko sekwencyjne dla krótkich serii wstawek (gdzie funkcja jest wywoływana bardzo szybko, na przykład podczas wstawiania wielu wierszy), co powoduje, że wstawione wiersze są losowo rozmieszczane na stronach danych tabeli wszystkich na końcu - eliminując w ten sposób hotspot z wkładek.

Ponadto, ponieważ wkładki są losowo rozdzielone, prawdopodobieństwo podziału strony jest znacznie zmniejszone.Podczas gdy strona podzielona tu i tam nie jest zbyt zła, efekty szybko się sumują. Z TOŻSAMOŚCIą, współczynnik wypełnienia strony jest całkiem bezużyteczny jako mechanizm strojenia i równie dobrze może być ustawiony na 100% - wiersze nigdy nie będą wstawiane na żadnej stronie oprócz ostatniej. Dzięki funkcji NewID() można faktycznie wykorzystać współczynnik wypełnienia jako narzędzie umożliwiające osiągnięcie wydajności. Współczynnik wypełnienia można ustawić na poziomie zbliżonym do szacowanego wzrostu wolumenu między odbudowaniami indeksów, a następnie zaplanować odbudowę poza godzinami szczytu za pomocą reindeksu dbcc. Skutecznie opóźnia to wydajność dzielenia stron do czasu poza szczytem.

Jeśli nawet myśli, być może trzeba włączyć replikację dla danej tabeli - wtedy równie dobrze można uczynić PK unikalnym identyfikatorem i oznaczyć pole guid jako ROWGUIDCOL. Replikacja będzie wymagać jednoznacznie wycenionego pola guid z tym atrybutem i doda jeden, jeśli nie istnieje. Jeśli istnieje odpowiednie pole, to po prostu użyje tego, które tam jest.

Kolejna ogromna korzyść dla użyciu GUID dla PK jest fakt, że wartość jest rzeczywiście gwarantuje wyjątkowy - nie tylko wśród wszystkich wartości generowanych przez tym serwerze, ale wszystkie wartości generowanych przez wszystkich komputerami - czy to będzie twój serwer db, serwer WWW, serwer aplikacji lub komputer klienta. Niemalże każdy współczesny język ma możliwość generowania prawidłowego guid teraz - w .NET można użyć System.Guid.NewGuid. Jest to BARDZO przydatne przy szczególnie zbiorze przechowywanych w pamięci podręcznej szczegółowych danych szczegółowych. Nie musisz stosować szalonych tymczasowych schematów kluczy, aby powiązać swoje rekordy, zanim zostaną zatwierdzone. Po prostu pobierasz całkowicie poprawny nowy Guid z systemu operacyjnego dla stałej wartości każdego nowego rekordu w momencie tworzenia rekordu.

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

+2

Przeczytaj Kimberly Tripp [GUIDs jako klucz podstawowy i/lub kluczowanie] (http://sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-classster-key.aspx) i [Disk przestrzeń jest tania - to ** NIE ** punkt!] (http://www.sqlskills.com/BLOGS/KIMBERLY/post/Disk-space-is-cheap.aspx) i wiele innych jej doskonałych blogów - ona ** wyraźnie ** pokazuje, jak zły jest pomysł klucza klastrowania w kolumnie GUID. Ponadto - hotspoty są mitem, który jest długo obalany - nie stanowi już żadnego problemu po SQL Server 6.5 .... –

+1

Fascynujące. Zajrzę do opcji "podziały stron i indeksuj strony", jeśli wydajność stanie się problemem. Dziękuję za to. –

0

Ja też zawsze słyszałem, że auto-inkrementujące int jest dobre dla wydajności, nawet jeśli w rzeczywistości jej nie używasz.

7

klucz podstawowy służy trzem celom:

  • oznacza, że ​​kolumna (a) powinna być unikalna
  • wskazuje, że kolumna (a) powinna być niezerowe
  • udokumentować zamiar, że jest to unikatowy identyfikator rzędu:

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

Trzeci powód jest dobry:

  • dla ludzi, więc można je łatwo zobaczyć swoją intencję
  • dla komputera, więc program, który może porównać lub w inny sposób przetwarzać tabelę można kwerendy bazy danych dla klucz podstawowy tabeli.

Klucz podstawowy nie musi być polem automatycznego zwiększania numeru, więc chciałbym powiedzieć, że dobrym pomysłem jest podanie kolumny guid jako klucza głównego.

+0

Z pewnością nie jest dobrym pomysłem posiadanie kolumny guid jako klucza podstawowego, ponieważ klucze podstawowe są klastrowane, a przewodniki są losowe. Oznacza to, że za każdym razem, gdy wstawiasz nowy wiersz, twoja tabela jest zasadniczo poddawana restrukturyzacji na dysku. Ludzie zwykle radzą, aby klucze podstawowe były sekwencyjnymi, ciągle rosnącymi typami, tak aby każdy nowy wiersz został przypięty na końcu stołu. –

+0

Klucz podstawowy jest domyślnie wspierany przez indeks klastrowany, ale można go usunąć (indeks klastrowany). –

+0

@MattHamilton re "... nie jest dobrym pomysłem, aby kolumna guid była kluczem podstawowym, ponieważ klucze podstawowe są klastrowane, a guidy losowe" aby to rozwiązać, można użyć funkcji "newsequentialid()" w SQL 2005/Edycja 2008: znalazłem wymagane [CodingHorror post] (http://www.codinghorror.com/blog/archives/000817.html), który mówi o tym ;-) –

1

Klucz podstawowy nie musi być polem autoinrementacji, w wielu przypadkach oznacza to tylko komplikowanie struktury tabeli.

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

Pod względem technicznym powinno to być pole, na którym każde inne pole w kodzie jest w pełni funkcjonalnie zależne. (Jeśli nie, możesz potrzebować normalizacji).

W praktyce problemy z wydajnością może oznaczać, że scalić tabele i użyć pola zwiększany, ale wydaje mi się przypomnieć coś o przedwczesna optymalizacja jest zły ...

6

Wystarczy skoków, ponieważ Matt przynętą mi trochę .

Należy zrozumieć, że chociaż indeks klastrowy jest domyślnie umieszczany w kluczu podstawowym tabeli, dwa pojęcia są oddzielne i należy je rozpatrywać osobno. CIX wskazuje sposób, w jaki dane są przechowywane i określane przez NCIX, podczas gdy PK zapewnia unikatowość 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 stolik". Najlepiej jest osobno zrozumieć koncepcje PK i CIX, aby można było podejmować rozsądne decyzje w zakresie projektowania baz danych.

Rob

3

Nikt nie odpowiedział rzeczywiste pytanie: jakie są plusy/minusy stole z Nie PK ani indeksu klastrowych. Moim zdaniem, jeśli zoptymalizujesz pod kątem szybszych wstawek (szczególnie przyrostowych insertów zbiorczych, np. Gdy zbiorczo ładujesz dane do niepustej tabeli), taka tabela: z brakiem klastrowanego indeksu, NO ograniczenia, NO Foreign Keys, NO Defaults i klucz podstawowy NO, w bazie danych z prostym modelem odzyskiwania, jest najlepszy. Teraz, jeśli chcesz zapytać o tę tabelę (w przeciwieństwie do skanowania jej w całości), możesz dodać niekonkurencyjne indeksy niesklasyfikowane według klastrów, ale zachowaj je do minimum.

+0

Właściwie to jest ** źle ** - jak Kimberly Tripp (Queen of Indexing) wyraźnie pokazuje: mając ** dobry ** indeks klastrowy ** zwiększy ** wydajność WSTAW! http: // sqlskills.com/BLOGI/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx –

+0

Nie nazwałbym tego wyraźnie pokazując :) Mówi o ogólnych zasadach, nie popierając jej oświadczenia z, cóż, cokolwiek, póki jestem Mówiąc o bardzo konkretnym scenariuszu, z jakim spotkałem się w mojej praktyce: wstawia się wiele potencjalnie setek milionów rekordów w niepustą tabelę, która nigdy nie jest aktualizowana ani dostępna w trybie losowego czytania, ale jest skanowana w całości. Przypuszczam, że może być więcej czynników niż indeksów. Zawsze sprawdzaj dzieci z optymalizacją. – zvolkov

0

Od kiedy wykonujecie replikację, wasze prawidłowa tożsamość jest czymś, o czym trzeba się ubrudzić. Uczyniłbym twój GUID kluczem podstawowym, ale nieklastrowany, ponieważ nie możesz użyć newsequentialid. To utwierdza mnie w najlepszym kursie. Jeśli nie stworzysz PK, ale umieścisz na nim unikalny indeks, prędzej czy później może to spowodować, że osoby, które utrzymują system, nie będą poprawnie rozumieć relacji FK, wprowadzając błędy.