Czy kolejność kolumn w indeksie PK ma znaczenie?
Tak.
Domyślnie ograniczenie klucza podstawowego jest wymuszane w SQL Server przez unikalny indeks klastrowany. Indeks klastrowy określa logiczną kolejność wierszy w tabeli. Może być dodanych wiele dodatkowych stron indeksu, które reprezentują górne poziomy indeksu b-drzewa, ale najniższy poziom liścia indeksu klastrowego jest po prostu logiczną kolejnością samych danych.
Aby to wyjaśnić, wiersze na stronie niekoniecznie są fizycznie przechowywane w klastrowanej kolejności kluczy indeksu. Na stronie znajduje się osobna struktura pośrednictwa, która przechowuje wskaźnik do każdego wiersza. Ta struktura jest sortowana według klastrowanych kluczy indeksu. Ponadto każda strona ma wskaźnik do poprzedniej i następnej strony na tym samym poziomie w klastrowanej kolejności kluczy indeksu.
W przypadku klastrowego klucza głównego (RowNumber, DataDate)
wiersze są logicznie sortowane najpierw według, RowNumber
a następnie według DataDate
- tak więc wszystkie wiersze, w których RowNumber = 1
są logicznie pogrupowane, a następnie wiersze gdzie RowNumber = 2
i tak dalej.
Po dodaniu nowych danych ( RowNumbers
od 1 do n) nowe wiersze logicznie należą do istniejących stron, więc SQL Server prawdopodobnie będzie musiał wykonać wiele pracy, dzieląc strony, aby zrobić miejsce. Cała ta aktywność generuje dużo dodatkowej pracy (w tym rejestrowanie zmian) bez żadnego zysku.
Dzielone strony również zaczynają się w około 50% puste, więc nadmierne dzielenie może również powodować niską gęstość stron (mniej wierszy niż optymalna na stronę). To nie tylko zła wiadomość do odczytu z dysku (niższa gęstość = więcej stron do przeczytania), ale także strony o mniejszej gęstości zajmują więcej miejsca w pamięci po buforowaniu.
Zmiana indeksu klastrowego na (DataDate, RowNumber
) oznacza, że nowe dane (o prawdopodobnie wyższej DataDates
niż obecnie przechowywana) są dołączane do logicznego końca indeksu klastrowego na nowych stronach. Spowoduje to usunięcie niepotrzebnych kosztów podziału stron i skróci czas ładowania. Mniej pofragmentowane dane oznaczają również, że aktywność odczytu z wyprzedzeniem (odczytywanie stron z dysku tuż przed ich potrzebą do zapytania w toku) może być bardziej wydajna.
Jeśli nic więcej, Twoje zapytania będą znacznie częściej wyszukiwane DataDate
niż RowNumber
. Indeks klastrowy włączony (DataDate, RowNumber
) obsługuje wyszukiwanie indeksowe DataDate
(a następnie RowNumber
). Istniejące ustawienie obsługuje tylko wyszukiwanie RowNumber
(i tylko wtedy, być może, włączenie DataDate
). Może się okazać, że można usunąć istniejący indeks nieklastrowany DataDate
po zmianie klucza podstawowego. Indeks klastrowy będzie szerszy niż indeks nieklastrowany, który zastępuje, dlatego należy przetestować, aby upewnić się, że wydajność pozostaje akceptowalna.
Podczas importowania nowych danych bcp
możesz uzyskać wyższą wydajność, jeśli dane w pliku importu zostaną posortowane według klastrowanych kluczy indeksu (najlepiej (DataDate, RowNumber
) i określisz bcp
opcję:
-h "ORDER(DataDate,RowNumber), TABLOCK"
Aby uzyskać najlepszą wydajność ładowania danych, możesz spróbować uzyskać minimalnie zarejestrowane wstawki. Aby uzyskać więcej informacji, zobacz:
Tak, kolejność jest krytyczna. Bardzo wątpię, czy kiedykolwiek zapytałeś RowNumber (np
WHERE RowNumber=1
.). Przeważnie szeregi czasowe są sprawdzane według date (WHERE DataDate BEWEEN @start AND @end
), a takie zapytania wymagałyby organizacji klastrowej doDataDate
.Fragmentacja jest ogólnie śledźem czerwonym. Ograniczenie fragmentacji nie powinno być tutaj twoim celem, ale właściwa organizacja dla twoich zapytań powinna. Zmniejszenie fragmentacji jest dobrym pomysłem, ale nie jest celem samym w sobie. Jeśli masz odpowiednio zorganizowany model danych, który odpowiada twojemu obciążeniu (twoje zapytania są odpowiednio uwzględnione) i masz pomiary, które pokazują, że fragmentacja wpływa na wydajność, możemy o tym porozmawiać.
źródło
WHERE
klauzulą w zapytaniach.