2009-08-20 12 views
333

Podczas studiów do egzaminu 70-433 zauważyłem, że możesz utworzyć indeks obejmujący na jeden z dwóch poniższych sposobów.Dlaczego warto używać klauzuli INCLUDE podczas tworzenia indeksu?

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3) 

- ALBO -

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3) 

INCLUDE klauzula jest dla mnie nowe. Dlaczego miałbyś go używać i jakie wskazówki sugerowałbyś, aby określić, czy utworzyć indeks obejmujący z klauzulą ​​INCLUDE czy bez niej?

Odpowiedz

290

Jeśli kolumna nie znajduje się w WHERE/JOIN/GROUP BY/ORDER BY, ale tylko na liście kolumn w klauzuli SELECT.

Klauzula INCLUDE dodaje dane na najniższym poziomie/liście zamiast w drzewie indeksów. Powoduje to, że indeks jest mniejszy, ponieważ nie jest częścią drzewa.

Oznacza to, że nie jest to użyteczne w przypadku predykatów, sortowania itp., O czym pisałem powyżej. Jednakże może być przydatne, jeśli masz resztkową wyszukiwanie w kilku rzędach z kolumny (ów) klucza

Another MSDN article with a worked example

+4

Czyli to byłaby technika tworzenia tańszej wersji indeksu objętego ubezpieczeniem? – JMarsch

+1

@ gbn, mógłbyś wyjaśnić to zdanie bardziej szczegółowo i wyjaśnić, dlaczego oznacza to, że klauzula include nie jest przydatna do sortowania, itp: "Klauzula INCLUDE dodaje dane na najniższym poziomie/liście zamiast w indeksie Drzewo to powoduje, że indeks jest mniejszy, ponieważ nie jest częścią drzewa " –

+2

@JMarsch: przepraszam za późną odpowiedź, ale tak, to jest dokładnie to, co jest. – gbn

15

podstawowe kolumny indeksu są sortowane, ale zawiera kolumny nie są sortowane. Oszczędza to zasoby w utrzymywaniu indeksu, a jednocześnie umożliwia dostarczenie danych w dołączonych kolumnach, aby pokryć zapytanie. Jeśli więc chcesz uwzględnić zapytania, możesz umieścić kryteria wyszukiwania, aby zlokalizować wiersze w posortowanych kolumnach indeksu, a następnie "uwzględnić" dodatkowe, nieposortowane kolumny z danymi innymi niż wyszukiwane. Zdecydowanie pomaga to w zmniejszeniu ilości sortowania i fragmentacji w konserwacji indeksu.

176

Użyjesz INCLUDE, aby dodać jedną lub więcej kolumn do poziomu liścia indeksu nieklastrowego, jeśli dzięki temu możesz "ukryć" swoje zapytania.

Wyobraź sobie, że musisz zapytać o identyfikator pracownika, identyfikator działu i nazwisko.

SELECT EmployeeID, DepartmentID, LastName 
FROM Employee 
WHERE DepartmentID = 5 

Jeśli zdarzy ci się mieć nieklastrowanym indeks (EmployeeID, DepartmentID), po znalezieniu pracowników dla danego działu, masz teraz zrobić „zakładka wyszukiwanie”, aby uzyskać rzeczywistą pełny rekord pracownika , aby uzyskać kolumnę nazwiska. To może być dość kosztowne pod względem wydajności, jeśli znajdziesz wielu pracowników.

Gdybyś wliczone że lastname w indeksie:

CREATE NONCLUSTERED INDEX NC_EmpDep 
    ON Employee(EmployeeID, DepartmentID) 
    INCLUDE (Lastname) 

następnie wszystkie potrzebne informacje są dostępne na poziomie liścia nieklastrowanym indeksu. Wystarczy wyszukać w indeksie nieklastrowanym i znaleźć pracowników dla danego działu, masz wszystkie niezbędne informacje, a wyszukiwanie zakładek dla każdego pracownika znalezionego w indeksie nie jest już konieczne -> oszczędzasz dużo czasu.

Oczywiście, nie można uwzględnić każdej kolumny w każdym indeksie nieklastrowanym - ale jeśli masz zapytania, których brakuje jednej lub dwóch kolumn, które mają być "pokryte" (i które często się przyzwyczajają), może to być bardzo pomocne ZAWIERAĆ je w odpowiedni indeks nieklastrowy.

+17

Czy na pewno chcesz użyć tego indeksu? Dlaczego EmployeeID? Potrzebujesz tylko DepartmentID w kluczowych kolumnach? Zostałaś tutaj cytowana jako autorytatywna: http://stackoverflow.com/q/6187904/27535 – gbn

+3

Twoje wyjaśnienie jest dobre, ale tak naprawdę nie jest zgodne z przypadkiem użycia, który opisujesz. Kluczowe kolumny powinny znajdować się na filtrze lub klawiszach 'JOIN' w zapytaniu, a" INCLUDE "muszą być danymi, które pobierasz, ale nie sortują. – JNK

+10

Przede wszystkim indeks Employee (EmployeeID, DepartmentID) nie będzie używany do filtrowania DepartmentID = 5. Ponieważ jego zamówienie nie pasuje do – AnandPhadke

5

Powody, dla których (w tym dane na poziomie liścia indeksu) zostały dobrze wyjaśnione.Powodem, dla którego podajesz dwa o tym tony, jest to, że kiedy uruchamiasz zapytanie, jeśli nie masz dołączonych dodatkowych kolumn (nowa funkcja w SQL 2005), SQL Server musi przejść do indeksu klastrowego, aby uzyskać dodatkowe kolumny co zajmuje więcej czasu i dodaje więcej obciążenia do usługi SQL Server, dysków i pamięci (bufor bufora jest specyficzny), ponieważ nowe strony danych są ładowane do pamięci, potencjalnie wypychając inne, częściej potrzebne dane z pamięci podręcznej bufora.

+0

jest jakiś sposób udowodnienia, że ​​faktycznie używa mniej pamięci? Jest to tym, czego bym się spodziewał, ale dostaję trochę informacji o tym w pracy – Asken

+0

Biorąc pod uwagę, że musisz załadować stronę ze sterty lub indeksu klastrowanego do pamięci, jak również stronę indeksu, co oznacza, że ​​umieszczasz duplikaty danych w pamięć matematyka staje się całkiem prosta. Jeśli chodzi o sposób na zmierzenie go, nie ma. – mrdenny

2

Istnieje ograniczenie całkowitej wielkości wszystkich kolumn, które zostały zaznaczone w definicji indeksu. Mimo to nigdy nie musiałem tworzyć tak szerokiego indeksu. Dla mnie większą zaletą jest to, że możesz pokryć więcej zapytań jednym indeksem, który zawiera kolumny, ponieważ nie trzeba ich definiować w żadnej określonej kolejności. Pomyśl o jest jako indeks w indeksie. Jednym z przykładów może być StoreID (gdzie StoreID ma niską selektywność, co oznacza, że ​​każdy sklep jest powiązany z wieloma klientami), a następnie dane demograficzne klientów (LastName, FirstName, DOB): Jeśli po prostu wstawiasz te kolumny w tej kolejności (StoreID , LastName, FirstName, DOB), możesz efektywnie wyszukiwać klientów, dla których znasz StoreID i LastName.

Z drugiej strony, zdefiniowanie indeksu na StoreID i w tym LastName, FirstName, kolumny DOB pozwolą ci w istocie na wykonanie dwóch predykatów index-index na StoreID, a następnie wyszukanie predykatu na dowolnej z dołączonych kolumn. Pozwoliłoby to objąć wszystkie możliwe permutacje wyszukiwania tak długo, jak zaczyna się od StoreID.

4

Dodatkowym argumentem, którego nie widziałem w udzielonych już odpowiedziach, jest to, że kolumny mogą zawierać typy danych, które nie są dozwolone jako kolumny klucza indeksów, takie jak varchar (max).

Umożliwia to włączenie takich kolumn do indeksu pokrywającego. Niedawno musiałem to zrobić, aby dostarczyć zapytanie wygenerowane przez nHibernate, które zawierało wiele kolumn w SELECT, z przydatnym indeksem.

16

Ta dyskusja toczy brakuje na ważną kwestię: Nie chodzi o to, czy „non-key-kolumny” są lepiej to jak indeksu -columns lub zawarte -columns.

Pytanie brzmi, jak drogo można użyć mechanizmu włączania, aby uwzględnić kolumny, które są niezbyt potrzebne w indeksie? (zwykle nie jest częścią klauzul where, ale często jest częścią selects). Więc zawsze jest dylemat:

  1. użycie indeksu na ID1, ID2 ... IDN sam lub
  2. użycie indeksu na ID1, ID2 ... IDN Plus obejmują col1, col2 ... Cöln

Gdzie: ID1, ID2 ... IDN są często stosowane w kolumnach ograniczeń i col1, col2 ... Cöln kolumny są często wybrane, ale zazwyczaj nie używane w ograniczeniach

(Opcja włączenia wszystkich tych kolumn jako części klucza indeksu jest po prostu zawsze niemądra (chyba że są one również używane w ograniczeniach) - ponieważ zawsze będzie droższa w utrzymaniu, ponieważ indeks musi być aktualizowany i sortowany nawet gdy "klucze" się nie zmieniły).

Więc użyj opcji 1 lub 2?

Odpowiedź: Jeśli twoja tabela jest rzadko aktualizowana - w większości wstawiana do/usuwana z - wtedy stosunkowo tanie jest używanie mechanizmu włączania, aby zawrzeć niektóre "gorące kolumny" (które są często używane w wybranych - ale nie często używane na ograniczeniach), ponieważ wstawianie/usuwanie wymaga, aby indeks był aktualizowany/sortowany w każdym razie, a zatem niewielki dodatkowy narzut związany jest z przechowywaniem kilku dodatkowych kolumn podczas aktualizacji indeksu. Narzut to dodatkowa pamięć i procesor używany do przechowywania nadmiarowych informacji w indeksie.

Jeśli kolumny rozważyć dodanie jako ujęte-kolumny są często aktualizowane (bez indeksowanych kluczowe -columns aktualizowany) - lub - jeśli jest ich tak wiele, że indeks będzie blisko kopię twojego stołu - skorzystaj z opcji 1, proponuję! Również jeśli dodamy pewną kolumnę (y) włączające, aby nie spowodować różnicy w wydajności - możesz pominąć pomysł dodania ich :) Sprawdź, czy są przydatne!

Średnia liczba wierszy na te same wartości w kluczach (id1, id2 ... idN) również może mieć znaczenie.

Należy zauważyć, że jeśli kolumna - która jest dodawana jako zawarte -column wskaźnika - służy do ograniczenia : Dopóki indeksu jako takie mogą być stosowane (na ograniczenia z indeksowanych key -columns) - wówczas SQL Server dopasowuje ograniczenie kolumny do indeksu (wartości węzła-liścia), zamiast iść drogim sposobem wokół samej tabeli.

Powiązane problemy