2010-08-20 24 views
6

Mamy starszą bazę danych, która jest serwerem dbl (2005 i 2008).Wcześniejsza baza danych serwera SQL do klastrowanego indeksu lub nie

Wszystkie klucze podstawowe w tabelach to UniqueIdentifiers.

Tabele obecnie nie mają utworzonego indeksu klastrowego, a obecnie występują problemy z wydajnością w tabelach zawierających jedynie rekordy 750 tys. Jest to pierwsza baza danych, na której pracowałem z unikalnymi identyfikatorami, jako jedynym kluczem podstawowym i nigdy nie widziałem serwera sql tak wolnego z powracającymi danymi.

Nie chcę tworzyć indeksu klastrowego na identyfikatorze uniqueidentifier, ponieważ nie są sekwencyjne, a zatem spowolnią aplikacje w dół, jeśli chodzi o wstawianie danych.

Nie można usunąć unikalnego identyfikatora, który jest używany do celów zarządzania tożsamością rekordu zdalnego witryny.

Zastanawiałem się nad dodaniem dużej kolumny tożsamości całkowitej do tabel i utworzeniem indeksu klastrowego w tej kolumnie z uwzględnieniem kolumny unikalnego identyfikatora.

tj

int identity - Pierwsza kolumna, aby utrzymać wkładkę przyspiesza unikalny identyfikator - w celu zapewnienia stosowania wciąż działa zgodnie z oczekiwaniami.

Celem jest poprawienie zapytania tożsamości i połączenie wydajności zapytań tabelowych.

Pytanie 1: Czy poprawi to wydajność zapytania dla db lub spowolni go?

Q2: Czy istnieje alternatywa do tej, której nie wymieniłem?

Dzięki Pete

Edit: Występ kwestie są na pobieranie danych za pośrednictwem wybranych sprawozdań szybko, zwłaszcza jeśli niektóre z bardziej „transakcyjnych/zmiany” tabele są połączone ze sobą.

Edit 2: sprzężeń pomiędzy stoły są generalnie wszystko pomiędzy klucza podstawowego i kluczy obcych, dla tabel, które mają klucze obce są one zawarte w nieklastrowanym indeksu, aby zapewnić więcej indeksu obejmującego.

Wszystkie tabele nie mają innych wartości, które zapewniłyby dobry indeks klastrowy.

Pochylam się raczej nad dodaniem dodatkowej kolumny tożsamości w każdej z tabel wysokiego obciążenia, a następnie dodaniu aktualnej kolumny Guid PK w indeksie klastrowym w celu zapewnienia najlepszej wydajności zapytania.

Edycja 3: Chciałbym oszacować, że 80% zapytań jest wykonywanych wyłącznie na kluczyach podstawowych i obcych za pośrednictwem mechanizmu dostępu do danych. Zasadniczo nasz model danych ma leniwy załadowane obiekty, które wykonują zapytanie po uzyskaniu dostępu, te zapytania używają identyfikatora obiektów i kolumny PK. Mamy dużą liczbę zapytań o wykluczanie/włączanie danych kierowanych przez użytkownika, które używają kolumn klucza obcego jako filtru opartego na kryteriach typu X, wykluczając następujące identyfikatory. Pozostałe 20% to miejsca, w których klauzule w kolumnach Enum (int) lub w zakresie dat, bardzo niewiele zapytań tekstowych są wykonywane w systemie.

Tam, gdzie to możliwe, dodałem już indeksy obejmujące najcięższe zapytania, ale jak na razie jestem rozczarowany wynikami. Jak mówi bluefooted, dane są przechowywane jako sterty.

+0

Czy istnieje obecnie indeks klastrowany na uniqueidentifiers? – jwsample

+0

Tak, mamy nie klastrowane indeksy na unikalnych identyfikatorów. – Peter

+0

Ponieważ masz co najmniej jeden indeks w tej kolumnie, już ponosisz karę wykonania we wkładce. W zależności od struktury tabeli możesz po prostu upuścić indeks nieklastrowy i przełączyć się na klaster z niewielkim wpływem na to, co aktualnie widzisz. – jwsample

Odpowiedz

4

Jeśli nie ma indeksu klastrowanego w tabeli, jest on przechowywany jako kupa zamiast b-drzewa. Dostęp do danych na stertach jest absolutnie okropny w SQL Server, więc zdecydowanie potrzebujesz dodać indeks klastrowy.

Zgadzam się z twoją analizą, że kolumna GUID jest złym wyborem dla klastrowania, szczególnie, że nie masz możliwości użycia NEWSEQUENTIALID(). Jeśli chcesz, możesz utworzyć nowy sztuczny klucz liczbowy, ale jeśli istnieje inna kolumna lub kombinacja kolumn, która ma sens jako indeks klastrowany, to też jest w porządku.

Czy masz często używane pole do skanowania zakresów? Które kolumny służą do łączenia? Czy istnieje kombinacja kolumn, które jednoznacznie identyfikują wiersz poza identyfikatorem GUID? Opublikowanie próbki modelu danych pomogłoby nam zaproponować dobrego kandydata do klastrowania.

+0

Niebieski niestety nie mogę opublikować modelu danych, ponieważ moja firma jest bardzo surowa, jeśli chodzi o tego typu rzeczy. W niektórych tabelach znajdują się kolumny daty używane do skanowania zakresów. Zasadniczo klucze główne (guidy) i klucze obce (guidy) są używane do łączenia, nie ma żadnych połączeń w kolumnach zwykłego tekstu. Zastanawiam się nad wykorzystaniem utworzonej daty, ale dodałem ją dopiero w ostatnim wydaniu i dlatego nie każdy wiersz ma tę wartość. Myślę, że dodanie sztucznej liczby całkowitej z włączoną tożsamością to ścieżka, którą wezmę. Guid to PK w każdym stole. – Peter

+0

Data jest często dobrym kandydatem do klucza klastrowania, zwłaszcza jeśli zapytania są często ograniczone przez zakres dat. Jeśli właśnie go dodałeś, prawdopodobnie nie jest on używany zbyt często, ale przynajmniej z utworzoną datą możesz zapewnić uporządkowane wstawianie, a tym samym zminimalizować podziały i fragmentację strony. Moja jedyna troska o sztuczny klucz jest taka, że ​​prawdopodobnie nigdy nie będzie użyteczny, chyba że zmienisz model danych, aby dołączyć do nowego klucza zamiast GUID. –

+0

Niezależnie od tego, co wybierzesz, koniecznie sprawdź również indeksy nieklastrowe. Jeśli Twój indeks GUID zawiera tylko kolumnę GUID, może nie być bardzo użyteczny. Możesz zbadać dodawanie niektórych kolumn do klauzuli INCLUDE, aby pokryć najczęstsze zapytania. –

2

Nie wiem, skąd pochodzą identyfikatory GUID, ale jeśli są generowane podczas wstawiania, użycie NEWSEQUENTIALID() w serwerze SQL zamiast NEWID() pomoże uniknąć problemów z fragmentacją podczas wstawiania.

Jeśli chodzi o wybór indeksu klastrowego, jak podaje Kimberly L. Tripp: here: "najważniejszym czynnikiem przy wyborze indeksu klastrowego jest jego wyjątkowość, wąskie i statyczne (stale rosnące ma inne zalety, minimalizując podziały). " Identyfikator GUID nie spełnia wąskiego wymagania w porównaniu do INT, a nawet BIGINT.

Kimberly ma również doskonały artykuł na temat GUIDs as PRIMARY KEYs and/or the clustering key.

+0

Identyfikatory są generowane przez .Net Frameworks Guid.NewGuid(); ponieważ architektura tego systemu została zbudowana, aby obiekty generowały własny identyfikator. (Znowu stary system.) – Peter

0

Nie wskazano, jakie są problemy z wydajnością. Jeśli najgorszym działaniem jest INSERT, to może twoje rozwiązanie jest poprawne. Jeśli jest to coś innego, powinienem sprawdzić, w jaki sposób indeks klastrowy może pomóc.

Możliwe jest sprawdzenie istniejących indeksów w tabeli i zapytań, które ich używają. Możesz być w stanie wybrać indeks, który po obniżeniu nieznacznie INSERTs zapewnia większe korzyści dla obecnych obszarów problemów z wydajnością.

+0

Masz rację, edytowałem post. Problemy pojawiają się, gdy wyszukujemy bardziej tabele transakcyjne (tj. Te, które zmieniają najbardziej, a nie tabele statyczne). To się komplikuje, jeśli dołączymy do siebie wiele tabel transakcyjnych. – Peter

1

Nie jest dla mnie w 100% zrozumiały: czy Twój wzorzec dostępu do numeru 1 służy do wysyłania zapytań do tabel przez GUID lub inne kolumny? A kiedy dołączasz do innych tabel, jakie kolumny (i typy danych) są najczęściej używane?

Nie mogę podać żadnych solidnych zaleceń, dopóki nie dowiem się więcej o tym, jak te identyfikatory GUID są używane. Rozumiem, że powiedziałeś, że są kluczami podstawowymi, ale to nie gwarantuje, że są one używane jako podstawowe warunki dla zapytań lub połączeń.

UPDATE

Teraz wiem, że trochę więcej, mam szaloną propozycję. Wykonaj klastrowanie tych tabel na identyfikatorach GUID, ale ustaw współczynnik wypełnienia na 60%. Spowoduje to złagodzenie problemu podziału strony i zapewni lepszą wydajność zapytań dotyczących tych szczeniąt.

Jeśli chodzi o używanie Guid.NewGuid(), wydaje się, że możesz wykonywać sekwencyjne identyfikatory GUI w języku C#. Znalazłem następujący kod tutaj na SO:

[DllImport("rpcrt4.dll", SetLastError = true)] 
static extern int UuidCreateSequential(out Guid guid); 

public static Guid SequentialGuid() 
{ 
    const int RPC_S_OK = 0; 
    Guid g; 
    if (UuidCreateSequential(out g) != RPC_S_OK) 
     return Guid.NewGuid(); 
    else 
     return g; 
} 

newsequentialID() jest właściwie tylko nakładką na UuidCreateSequential.Jestem pewien, że jeśli nie możesz użyć tego bezpośrednio na kliencie, możesz wymyślić sposób na szybki powrót do serwera, aby uzyskać nowy identyfikator sekwencyjny stamtąd, być może nawet z tabelą "dystrybutora" i procedura składowana do wykonania zadania.

+0

Edytowałem oryginalny wpis, patrz edytuj 2 i 3. – Peter

+0

Wypełnienie jest zdecydowanie możliwe, chociaż znowu będzie nadęty indeks. Posiadanie kluczy GUID w indeksie klastrowym nie jest idealne, ale ponieważ utknąłeś już na GUID-ach i są one używane dla większości twoich połączeń, być może będziesz musiał po prostu z tym skończyć. Myślę, że w dolnej linii trzeba zrobić kilka testów, aby znaleźć najlepszy sposób. Czy masz system testowy, którego możesz użyć do wypróbowania różnych metod? –

+0

Zgadzam się na to, że warto używać tych ogromnych identyfikatorów GUID, a obniżenie liczby wierszy na stronę poprzez zmniejszenie współczynnika wypełnienia jest niefortunne, ale jeśli chce poprawić wydajność aktualizacji kosztem wydajności odczytu, to jest droga. Nie jest to nawet prosta propozycja, ponieważ podział strony już zmniejsza gęstość rzędów stron ... – ErikE

Powiązane problemy