Nella memoria orientata alle righe di SQL Server gli indici cluster e non cluster sono organizzati come alberi B.
( Fonte immagine )
La differenza chiave tra indici cluster e indici non cluster è che il livello foglia dell'indice cluster è la tabella. Ciò ha due implicazioni.
- Le righe nelle pagine foglia dell'indice cluster contengono sempre qualcosa per ciascuna delle colonne (non sparse) nella tabella (il valore o un puntatore al valore effettivo).
- L'indice cluster è la copia principale di una tabella.
Gli indici non cluster possono anche fare il punto 1 usando la INCLUDE
clausola (Since SQL Server 2005) per includere esplicitamente tutte le colonne non chiave ma sono rappresentazioni secondarie e c'è sempre un'altra copia dei dati intorno (la tabella stessa).
CREATE TABLE T
(
A INT,
B INT,
C INT,
D INT
)
CREATE UNIQUE CLUSTERED INDEX ci ON T(A,B)
CREATE UNIQUE NONCLUSTERED INDEX nci ON T(A,B) INCLUDE (C,D)
I due indici sopra saranno quasi identici. Con le pagine dell'indice di livello superiore contenenti i valori per le colonne chiave A,B
e le pagine di livello foglia contenentiA,B,C,D
Può esserci un solo indice cluster per tabella, poiché le righe di dati stesse possono essere ordinate in un solo ordine.
La citazione precedente dai libri online di SQL Server provoca molta confusione
Secondo me sarebbe molto meglio come.
Può esserci un solo indice cluster per tabella, poiché le righe a livello foglia dell'indice cluster sono le righe della tabella.
La citazione dei libri online non è errata, ma si dovrebbe essere chiari sul fatto che lo "smistamento" di indici sia non cluster che cluster sia logico non fisico. Se leggi le pagine a livello di foglia seguendo l'elenco collegato e leggi le righe sulla pagina in ordine di array di slot, allora leggerai le righe dell'indice in ordine ordinato ma fisicamente le pagine potrebbero non essere ordinate. La convinzione comunemente diffusa che con un indice cluster le righe siano sempre archiviate fisicamente sul disco nello stesso ordine della chiave di indice è falsa.
Questa sarebbe una realizzazione assurda. Ad esempio, se una riga viene inserita nel mezzo di una tabella da 4 GB, SQL Server non deve copiare 2 GB di dati nel file per fare spazio alla riga appena inserita.
Invece si verifica una divisione di pagina. Ogni pagina a livello foglia di indici sia cluster che non cluster ha l'indirizzo ( File:Page
) della pagina successiva e precedente in ordine di chiave logica. Queste pagine non devono necessariamente essere contigue o in ordine di chiave.
ad esempio la catena di pagine collegate potrebbe essere 1:2000 <-> 1:157 <-> 1:7053
Quando si verifica una divisione di pagina, una nuova pagina viene allocata da qualsiasi parte del filegroup (da un'estensione mista, per tabelle piccole o un'estensione uniforme non vuota appartenente a quell'oggetto o un'estensione uniforme appena allocata). Questo potrebbe non essere nemmeno nello stesso file se il gruppo di file ne contiene più di uno.
Il grado in cui l'ordine logico e la contiguità differiscono dalla versione fisica idealizzata è il grado di frammentazione logica.
In un database appena creato con un singolo file ho eseguito il seguente.
CREATE TABLE T
(
X TINYINT NOT NULL,
Y CHAR(3000) NULL
);
CREATE CLUSTERED INDEX ix
ON T(X);
GO
--Insert 100 rows with values 1 - 100 in random order
DECLARE @C1 AS CURSOR,
@X AS INT
SET @C1 = CURSOR FAST_FORWARD
FOR SELECT number
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 1 AND 100
ORDER BY CRYPT_GEN_RANDOM(4)
OPEN @C1;
FETCH NEXT FROM @C1 INTO @X;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO T (X)
VALUES (@X);
FETCH NEXT FROM @C1 INTO @X;
END
Quindi controllato il layout della pagina con
SELECT page_id,
X,
geometry::Point(page_id, X, 0).STBuffer(1)
FROM T
CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
ORDER BY page_id
I risultati sono stati ovunque. La prima riga nell'ordine delle chiavi (con valore 1 - evidenziato con la freccia in basso) era quasi l'ultima pagina fisica.
La frammentazione può essere ridotta o rimossa ricostruendo o riorganizzando un indice per aumentare la correlazione tra ordine logico e ordine fisico.
Dopo aver corso
ALTER INDEX ix ON T REBUILD;
Ho ottenuto il seguente
Se la tabella non ha un indice cluster, viene chiamata heap.
Gli indici non cluster possono essere costruiti su un heap o un indice cluster. Contengono sempre un posizionatore di riga nella tabella di base. Nel caso di un heap, questo è un identificatore di riga fisica (rid) ed è costituito da tre componenti (File: Pagina: Slot). Nel caso di un indice cluster il localizzatore di righe è logico (la chiave dell'indice cluster).
Per quest'ultimo caso, se l'indice non cluster include già naturalmente le colonne chiave IC come colonne chiave NCI o INCLUDE
colonne -d, non viene aggiunto nulla. In caso contrario, le colonne mancanti della chiave CI vengono silenziosamente aggiunte all'NCI.
SQL Server garantisce sempre che le colonne chiave siano univoche per entrambi i tipi di indice. Il meccanismo in cui questo viene applicato per gli indici non dichiarati come unici differisce tuttavia tra i due tipi di indice.
Gli indici cluster vengono uniquifier
aggiunti per tutte le righe con valori chiave che duplicano una riga esistente. Questo è solo un numero intero crescente.
Per gli indici non cluster non dichiarati come univoci SQL Server aggiunge silenziosamente il localizzatore di righe alla chiave dell'indice non cluster. Questo vale per tutte le righe, non solo per quelle che sono effettivamente duplicate.
La nomenclatura cluster vs non cluster viene utilizzata anche per gli indici dei negozi di colonne. Gli carta Miglioramenti a SQL Server colonna memorizza gli stati
Sebbene i dati dell'archivio di colonne non siano realmente "raggruppati" su nessuna chiave, abbiamo deciso di mantenere la tradizionale convenzione SQL Server di fare riferimento all'indice primario come indice cluster.