2010-08-27 24 views
52

Qualcuno può spiegare questo due - Colonna chiave indice Colonna indice VS inclusa?Indice Chiave Colonna Indice VS Colonna inclusa

Attualmente, ho un indice che ha 4 colonne chiave indice e 0 colonne incluse.

Grazie

+0

C'è il miglioramento delle prestazioni leggera se le chiavi non necessari sono inclusi nella colonna: https://logicalread.com/ tidbit-sql-server indexing-part-1/ – Sun

risposta

90

Le colonne chiave dell'indice fanno parte del b-tree dell'indice. Le colonne incluse non lo sono.

prendere due indici:

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

index1 è più adatto per questo tipo di query:

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

Mentre index2 è più adatto per questo tipo di query:

SELECT col2, col3 FROM table1 WHERE col1 = x 

Nella prima query, index1 fornisce a meccanismo per identificare rapidamente le file di interesse. La query verrà (probabilmente) eseguita come ricerca per indice, seguita da una ricerca nei segnalibri per recuperare le righe complete.

Nella seconda query, index2 funge da indice di copertura. SQL Server non deve necessariamente colpire la tabella di base, poiché l'indice fornisce tutti i dati necessari per soddisfare la query. index1 potrebbe anche fungere da indice di copertura in questo caso.

Se si desidera un indice di copertura, ma non si desidera aggiungere tutte le colonne alla b-tree perché non si cerca su di esse, o non può perché non sono un tipo di dati consentito (ad esempio, XML), utilizzare la clausola INCLUDE.

6

colonne incluse non fanno parte della chiave per l'indice, ma esistono sull'indice. Essenzialmente i valori saranno duplicati, quindi c'è un overhead di archiviazione, ma c'è una maggiore possibilità che il tuo indice copra (cioè essere selezionato da Query Optimizer per) più query. Questa duplicazione migliora anche le prestazioni durante l'esecuzione di query, poiché il motore di database può restituire il valore senza dover controllare la tabella stessa.

Solo gli indici non cluster possono includere colonne, poiché in un indice cluster ogni colonna viene effettivamente inclusa.

+0

+1 IOW la densità fila di indici rivestimento è maggiore, il che significa meno pagine devono essere prelevati da SQL. – StuartLC

+0

@nonnb: con un indice di copertura, non è necessaria la ricerca di un segnalibro. Sì, vengono lette meno pagine e SQL Server deve fare meno lavoro, ma questo perché tutte le informazioni necessarie sono contenute all'interno dell'indice. La "densità dell'informazione" può essere più alta, per alcune definizioni. Non sei sicuro di cosa intendi per densità di file, però. –

11

Pensiamo al libro. Ogni pagina del libro ha il numero di pagina. Tutte le informazioni in questo libro sono presentate in sequenza in base a questo numero di pagina. Parlando nei termini del database, il numero di pagina è l'indice cluster. Ora pensa al glossario alla fine del libro. Questo è in ordine alfabetico e ti consente di trovare rapidamente il termine del glossario specifico del numero di pagina. Questo rappresenta l'indice non in cluster con il termine glossario come colonna chiave.

Ora assumendo che ogni pagina mostri anche il titolo "capitolo" in alto. Se si desidera trovare in quale capitolo si trova il termine del glossario, è necessario cercare in quale pagina # si descriva il termine del glossario, successivamente - aprire la pagina corrispondente e vedere il titolo del capitolo sulla pagina. Ciò rappresenta chiaramente la ricerca della chiave: quando è necessario trovare i dati dalla colonna non indicizzata, è necessario trovare il record di dati effettivo (indice cluster) e osservare il valore di questa colonna. La colonna inclusa aiuta in termini di prestazioni - si pensi al glossario in cui ogni titolo del capitolo include oltre al termine del glossario. Se è necessario conoscere il capitolo a cui appartiene il termine del glossario - non è necessario aprire la pagina effettiva - è possibile ottenerlo quando si cerca il termine del glossario.

Quindi le colonne incluse sono come quei titoli dei capitoli. L'indice non clusterizzato (glossario) ha attributo di addizione come parte dell'indice non in cluster. Indice non è ordinato per colonne incluse - attribuisce solo aggiuntivi che aiuta ad accelerare la ricerca (ad esempio, non è necessario per aprire la pagina attuale perché l'informazione è già nell'indice glossario).

Esempio:

Crea tabella 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 

stored procedure sceneggiatura

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 

Utilizzando quanto sopra SP è possibile inserire 200000 record contemporaneamente.

È possibile vedere che esiste un indice cluster nella colonna "EnrollMentId".

Ora creare un indice non clusterizzato su colonna "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 

Ora eseguire la seguente query

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. 

Ora eliminare l'indice non cluster sopra e ricreare con seguente script

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 

getterà il seguente errore

Msg 1919, livello 16, stato 1, riga 1 colonna 'Detail1' nella tabella 'dbo.Profile' è di un tipo che non è valido per l'utilizzo come una colonna chiave in un indice.

Perché non possiamo usare varchar tipo di dati (max) come colonna chiave.

Ora crea un indice non cluster con colonne incluse utilizzando script seguente

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 

Ora eseguire la seguente query

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 -quando-creare-un-index? forum = sqldatabaseengine – mrd3650

Problemi correlati