2010-08-27 21 views
52

Może ktoś wyjaśnić to dwa - kolumna indeks klucza VS Index wliczony w kolumnie?Główna kolumna klucz VS Główna wliczony Kolumna

Obecnie mam indeks, który ma 4 Index kolumna klucz i 0 wliczony kolumnę.

Dzięki

+0

Jest nieznaczna poprawa wydajności jeśli niepotrzebne klucze znajdują się w załączonej kolumnie: https://logicalread.com/ tidbit-sql-server-indexing-part-1/ – Sun

Odpowiedz

90

indeks klucza kolumny są częścią drzewa b indeksu. Uwzględnione kolumny nie są.

Weź dwa indeksy:

CREATE INDEX index1 ON table1 (col1, col2, col3) 
CREATE INDEX index2 ON table1 (col1) INCLUDE (col2, col3) 

index1 lepiej nadaje się do tego rodzaju zapytania:

SELECT * FROM table1 WHERE col1 = x AND col2 = y AND col3 = z 

Zważywszy index2 lepiej nadaje się do tego rodzaju zapytania:

SELECT col2, col3 FROM table1 WHERE col1 = x 

W pierwszym zapytaniu index1 zapewnia mechanizm szybkiego identyfikowania interesujących nas rzędów. Zapytanie (prawdopodobnie) zostanie wykonane jako poszukiwanie indeksu, po którym następuje wyszukiwanie zakładki w celu pobrania pełnych wierszy.

W drugim zapytaniu index2 działa jako indeks zakrywający. SQL Server nie musi w ogóle uderzać w tabelę podstawową, ponieważ indeks dostarcza wszystkich danych, które są potrzebne do spełnienia zapytania. index1 może również pełnić rolę indeksu pokrywającego w tym przypadku.

Jeśli potrzebujesz indeksu pokrywającego, ale nie chcesz dodawać wszystkich kolumn do drzewa b, ponieważ ich nie szukasz, lub nie, ponieważ nie są one dozwolonymi typami danych (np. XML), użyj klauzuli INCLUDE.

6

uwzględnionych kolumn nie tworzą część klucza dla indeksu, ale one istnieją na indeksie. Zasadniczo wartości zostaną zduplikowane, więc istnieje narzut związany z pamięcią masową, ale istnieje większa szansa, że ​​indeks pokryje (tj. Zostanie wybrany przez optymalizator zapytań dla) więcej zapytań. To duplikowanie poprawia również wydajność podczas odpytywania, ponieważ silnik bazy danych może zwrócić wartość bez konieczności patrzenia na samą tabelę.

Tylko nieklastrowane indeksy mogły zawierać kolumny, ponieważ w indeksie klastrowym każda kolumna jest skutecznie uwzględniana.

+0

+1 IOW gęstość rzędów indeksów pokrywających jest wyższa, co oznacza, że ​​mniej stron musi być pobranych przez SQL. – StuartLC

+0

@nonnb: z indeksem pokrywającym nie potrzebujesz wyszukiwania zakładek. Tak, mniej stron jest odczytywanych, a SQL Server ma mniej pracy, ale to dlatego, że wszystkie potrzebne informacje są zawarte w indeksie. "Gęstość informacji" może być wyższa, z pewnymi jej definicjami. Nie wiesz, co masz na myśli przez gęstość rzędów. –

11

Pomyślmy o książce. Każda strona w książce ma numer strony. Wszystkie informacje w tej książce są prezentowane sekwencyjnie na podstawie tego numeru strony. Mówiąc w kategoriach baz danych, numer strony jest indeksem klastrowym. Teraz pomyśl o glosariuszu na końcu książki. Jest to uporządkowane alfabetycznie i pozwala szybko znaleźć numer strony, do której należy dany termin glosariusza. Reprezentuje to indeks nieklastrowy z glosariuszem jako kluczową kolumną.

Teraz zakładając, że każda strona pokazuje także „Rozdział” tytuł na górze. Jeśli chcesz znaleźć w jakim rozdziale jest termin glosariusz, musisz sprawdzić, która strona # opisuje termin słownikowy, następnie - otwórz odpowiednią stronę i zobacz tytuł rozdziału na stronie. To wyraźnie reprezentuje kluczowe wyszukiwanie - gdy potrzebujesz znaleźć dane z nieindeksowanej kolumny, musisz znaleźć faktyczny rekord danych (indeks klastrowy) i spojrzeć na tę wartość kolumny. Uwzględniona kolumna pomaga pod względem wydajności - zastanów się nad glosariuszem, w którym każdy tytuł rozdziału zawiera dodatkowo termin glosariusza. Jeśli chcesz dowiedzieć się, do jakiego rozdziału należy termin glosariuszowy - nie musisz otwierać aktualnej strony - możesz ją uzyskać, gdy będziesz wyszukiwał termin glosariusza.

Kolumna zawiera tak jak te tytuły rozdziałów. Indeks nieklastrowy (glosariusz) ma atrybut dodawania jako część indeksu nieklastrowego. Indeks nie jest sortowany według uwzględnionych kolumn - to tylko dodatkowe atrybuty, które pomagają przyspieszyć wyszukiwanie (np. Nie trzeba otwierać rzeczywistej strony, ponieważ informacje są już w indeksie glosariusza).

Przykład:

Create Table Script

CREATE TABLE [dbo].[Profile](
    [EnrollMentId] [int] IDENTITY(1,1) NOT NULL, 
    [FName] [varchar](50) NULL, 
    [MName] [varchar](50) NULL, 
    [LName] [varchar](50) NULL, 
    [NickName] [varchar](50) NULL, 
    [DOB] [date] NULL, 
    [Qualification] [varchar](50) NULL, 
    [Profession] [varchar](50) NULL, 
    [MaritalStatus] [int] NULL, 
    [CurrentCity] [varchar](50) NULL, 
    [NativePlace] [varchar](50) NULL, 
    [District] [varchar](50) NULL, 
    [State] [varchar](50) NULL, 
    [Country] [varchar](50) NULL, 
    [UIDNO] [int] NOT NULL, 
    [Detail1] [varchar](max) NULL, 
    [Detail2] [varchar](max) NULL, 
    [Detail3] [varchar](max) NULL, 
    [Detail4] [varchar](max) NULL, 
PRIMARY KEY CLUSTERED 
(
    [EnrollMentId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

GO 

SET ANSI_PADDING OFF 
GO 

Procedura składowana skrypt

CREATE Proc [dbo].[InsertIntoProfileTable] 
As 
BEGIN 
SET NOCOUNT ON 
Declare @currentRow int 
Declare @Details varchar(Max) 
Declare @dob Date 
set @currentRow =1; 
set @Details ='Let''s think about the book. Every page in the book has the page number. All information in this book is presented sequentially based on this page number. Speaking in the database terms, page number is the clustered index. Now think about the glossary at the end of the book. This is in alphabetical order and allow you to quickly find the page number specific glossary term belongs to. This represents non-clustered index with glossary term as the key column.  Now assuming that every page also shows "chapter" title at the top. If you want to find in what chapter is the glossary term, you have to lookup what page # describes glossary term, next - open corresponding page and see the chapter title on the page. This clearly represents key lookup - when you need to find the data from non-indexed column, you have to find actual data record (clustered index) and look at this column value. Included column helps in terms of performance - think about glossary where each chapter title includes in addition to glossary term. If you need to find out what chapter the glossary term belongs - you don''t need to open actual page - you can get it when you lookup the glossary term.  So included column are like those chapter titles. Non clustered Index (glossary) has addition attribute as part of the non-clustered index. Index is not sorted by included columns - it just additional attributes that helps to speed up the lookup (e.g. you don''t need to open actual page because information is already in the glossary index).' 
while(@currentRow <=200000) 
BEGIN 
insert into dbo.Profile values('FName'+ Cast(@currentRow as varchar), 'MName' + Cast(@currentRow as varchar), 'MName' + Cast(@currentRow as varchar), 'NickName' + Cast(@currentRow as varchar), DATEADD(DAY, ROUND(10000*RAND(),0),'01-01-1980'),NULL, NULL, @currentRow%3, NULL,NULL,NULL,NULL,NULL, [email protected],@Details,@Details,@Details,@Details) 
set @currentRow +=1; 
END 

SET NOCOUNT OFF 
END 

GO 

Stosując powyższą SP można wstawić 200000 rekordy w tym samym czasie.

Można zobaczyć, że istnieje indeks klastrowany w kolumnie "EnrollMentId".

Teraz Utwórz indeks nie klastrowany w kolumnie "UIDNO".

Script

CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-223309] ON [dbo].[Profile] 
(
    [UIDNO] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

Teraz uruchom następującą kwerendę

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile 
--Takes about 30-50 seconds and return 200,000 results. 

Query 2

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile 
where DOB between '01-01-1980' and '01-01-1985' 
--Takes about 10-15 seconds and return 36,479 records. 

Teraz upuść powyższy wskaźnik nieklastrowanym i ponownie utworzyć z następujących skrypt

CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-231011] ON [dbo].[Profile] 
(
    [UIDNO] ASC, 
    [FName] ASC, 
    [DOB] ASC, 
    [MaritalStatus] ASC, 
    [Detail1] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

To wygeneruje następujący błąd

Msg 1919, Level 16, State 1, Linia 1 Kolumna 'Detail1' na stole 'dbo.Profile' jest typu, który jest nieważny do użytku jako kluczowa kolumna w indeksie.

Ponieważ nie możemy użyć typu danych varchar (Max) jako kolumny klucza.

teraz utworzyć nieklastrowanym indeks z uwzględnionych kolumn stosując następujący skrypt

CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-231811] ON [dbo].[Profile] 
(
    [UIDNO] ASC 
) 
INCLUDE ( [FName], 
    [DOB], 
    [MaritalStatus], 
    [Detail1]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

Teraz uruchom następującą kwerendę

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile --Takes about 20-30 seconds and return 200,000 results. 

Query 2

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile 
where DOB between '01-01-1980' and '01-01-1985' 
--Takes about 3-5 seconds and return 36,479 records. 
+4

http://social.msdn.microsoft.com/Forums/sqlserver/en-US/7fb76e54-4912-48fa-8816-56878e88a176/whats-the-difference-between-index-key-columns-and-include-columns -when-creation-an-index? forum = sqldatabaseengine – mrd3650

Powiązane problemy