Ottima domanda in quanto è un concetto così importante. Questo è un argomento importante e ciò che sto per mostrarti è una semplificazione in modo da poter comprendere i concetti di base.
In primo luogo quando vedi la tabella di pensiero indice cluster . Nel server SQL se una tabella non contiene un indice cluster è un heap. La creazione di un indice cluster sulla tabella trasforma effettivamente la tabella in una struttura di tipo b-tree. L'indice cluster È la tua tabella, non è separato dalla tabella
Ti sei mai chiesto perché puoi avere un solo indice cluster? Bene, se avessimo due indici raggruppati avremmo bisogno di due copie della tabella. Dopotutto contiene i dati.
Proverò a spiegarlo usando un semplice esempio.
NOTA: ho creato la tabella in questo esempio e l'ho riempita con oltre 3 milioni di voci casuali. Quindi ha eseguito le query effettive e incollato qui i piani di esecuzione.
Ciò di cui hai veramente bisogno è la notazione O o l' efficienza operativa . Supponiamo che tu abbia la seguente tabella.
CREATE TABLE [dbo].[Customer](
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[CustomerName] [varchar](100) NOT NULL,
[CustomerSurname] [varchar](100) NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Quindi qui abbiamo una tabella di base con una chiave cluster su CustomerID (la chiave primaria è raggruppata per impostazione predefinita). Pertanto, la tabella viene organizzata / ordinata in base alla chiave primaria CustomerID. I livelli intermedi conterranno i valori CustomerID. Le pagine di dati conterranno l'intera riga, quindi è la riga della tabella.
Creeremo anche un indice non cluster nel campo CustomerName. Il seguente codice lo farà.
CREATE NONCLUSTERED INDEX [ix_Customer_CustomerName] ON [dbo].[Customer]
(
[CustomerName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF
, DROP_EXISTING = OFF, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
Quindi in questo indice troverai nelle pagine di dati / nodi a livello foglia un puntatore ai livelli intermedi nell'indice cluster. L'indice è organizzato / ordinato attorno al campo CustomerName. Pertanto, il livello intermedio contiene i valori CustomerName e il livello foglia conterrà il puntatore (questi valori del puntatore sono in realtà i valori della chiave primaria o la colonna CustomerID).
Bene, quindi se eseguiamo la seguente query:
SELECT * FROM Customer WHERE CustomerID = 1
Probabilmente SQL leggerà l'indice cluster tramite un'operazione di ricerca. Un'operazione di ricerca è una ricerca binaria che è molto più efficiente di una scansione che è una ricerca sequenziale. Quindi nel nostro esempio sopra l'indice viene letto e usando una ricerca binaria SQL può eliminare i dati che non corrispondono ai criteri che stiamo cercando. Vedi la schermata allegata per il piano di query.
Quindi il numero di operazioni o Notazione O per l'operazione di ricerca è il seguente:
- Effettua la ricerca binaria sull'indice cluster confrontando il valore cercato con i valori a livello intermedio.
- Restituisce i valori corrispondenti (ricorda che l'indice cluster ha tutti i dati in esso contenuti può restituire tutte le colonne dall'indice in quanto sono i dati della riga)
Quindi sono due operazioni. Tuttavia, se abbiamo eseguito la seguente query:
SELECT * FROM Customer WHERE CustomerName ='John'
SQL ora utilizzerà l'indice non cluster sul CustomerName per eseguire la ricerca. Tuttavia, poiché si tratta di un indice non cluster, non contiene tutti i dati nella riga.
Quindi SQL eseguirà la ricerca a livelli intermedi per trovare i record corrispondenti quindi eseguirà una ricerca utilizzando i valori restituiti per eseguire un'altra ricerca sull'indice cluster (ovvero la tabella) per recuperare i dati effettivi. Sembra confuso, lo so, ma continuate a leggere e tutto diventerà chiaro.
Poiché il nostro indice non cluster contiene solo il campo CustomerName (i valori dei campi indicizzati archiviati nei nodi intermedi) e il puntatore ai dati che è CustomerID, l'indice non ha alcuna registrazione del CustomerSurname. Il Cognome cliente deve essere recuperato dall'indice o dalla tabella cluster.
Quando eseguo questa query ottengo il seguente piano di esecuzione:
Ci sono due cose importanti da notare nella schermata qui sopra
- SQL sta dicendo che ho un indice mancante (il testo in verde). SQL sta suggerendo di creare un indice su CustomerName che includa CustomerID e CustomerSurname.
- Vedrai anche che il 99% del tempo della query viene impiegato per eseguire una ricerca della chiave sull'indice della chiave primaria / indice cluster.
Perché SQL suggerisce di nuovo l'indice su CustomerName? Bene, poiché l'indice contiene solo CustomerID e CustomerName SQL deve ancora trovare CustomerSurname dalla tabella / dagli indici cluster.
Se abbiamo creato l'indice e includessimo la colonna CustomerSurname nell'indice, SQL sarebbe in grado di soddisfare l'intera query semplicemente leggendo l'indice non cluster. Questo è il motivo per cui SQL sta suggerendo di cambiare il mio indice non cluster.
Qui puoi vedere l'operazione aggiuntiva che SQL deve fare per ottenere la colonna CustomerSurname dalla chiave cluster
Pertanto, il numero di operazioni è il seguente:
- Effettua la ricerca binaria su un indice non cluster confrontando il valore cercato con i valori nel livello intermedio
- Per i nodi corrispondenti leggere il nodo a livello di foglia che conterrà il puntatore per i dati nell'indice cluster (i nodi a livello di foglia conterranno comunque i valori della chiave primaria).
- Per ogni valore restituito, fai una lettura sull'indice cluster (la tabella) per ottenere i valori di riga qui, leggeremo il Cognome del cliente.
- Restituisce le righe corrispondenti
Sono 4 operazioni per ottenere i valori. Il doppio della quantità di operazioni necessarie rispetto alla lettura dell'indice cluster. Lo dimostra che il tuo indice cluster è il tuo indice più potente in quanto contiene tutti i dati.
Quindi, solo per chiarire un ultimo punto. Perché dico che il puntatore nell'indice non cluster è il valore della chiave primaria? Bene per dimostrare che i nodi a livello foglia dell'indice non cluster contengono il valore della chiave primaria, cambio la mia query in:
SELECT CustomerID
FROM Customer
WHERE CustomerName='Jane'
In questa query SQL può leggere l'ID cliente dall'indice non cluster. Non è necessario effettuare una ricerca sull'indice cluster. Questo si può vedere dal piano di esecuzione che assomiglia a questo.
Notare la differenza tra questa query e la query precedente. Non c'è ricerca. SQL può trovare tutti i dati nell'indice non cluster
Spero che tu possa iniziare a capire che l'indice cluster è la tabella e che gli indici non cluster NON contengono tutti i dati. L'indicizzazione accelera le selezioni a causa del fatto che è possibile eseguire ricerche binarie ma solo gli indici cluster contengono tutti i dati. Pertanto, una ricerca su un indice non cluster determinerà quasi sempre il caricamento di valori dall'indice cluster. Queste operazioni extra rendono gli indici non cluster meno efficienti di un indice cluster.
Mi auguro questo chiarisca tutto. Se qualcosa non ha senso, si prega di inviare un commento e cercherò di chiarire. È piuttosto tardi qui e il mio cervello si sente un po 'piatto. Tempo per un toro rosso.