Dans le stockage orienté ligne SQL Server, les index cluster et non cluster sont organisés en arborescences B.
( Source de l'image )
La principale différence entre les index cluster et les index non cluster est que le niveau feuille de l'index cluster est la table. Cela a deux implications.
- Les lignes des pages feuilles d'index cluster contiennent toujours quelque chose pour chacune des colonnes (non éparses) de la table (soit la valeur, soit un pointeur sur la valeur réelle).
- L'index cluster est la copie principale d'une table.
Les index non clusterisés peuvent également faire le point 1 en utilisant la INCLUDE
clause (depuis SQL Server 2005) pour inclure explicitement toutes les colonnes non clés mais ce sont des représentations secondaires et il y a toujours une autre copie des données autour (la table elle-même).
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)
Les deux indices ci-dessus seront presque identiques. Avec les pages d'index de niveau supérieur contenant des valeurs pour les colonnes clés A,B
et les pages de niveau feuille contenantA,B,C,D
Il ne peut y avoir qu'un seul index cluster par table, car les lignes de données elles-mêmes peuvent être triées dans un seul ordre.
La citation ci-dessus des livres en ligne de SQL Server provoque beaucoup de confusion
À mon avis, ce serait beaucoup mieux formulé comme.
Il ne peut y avoir qu'un seul index cluster par table, car les lignes de niveau feuille de l'index cluster sont les lignes de la table.
La citation en ligne des livres n'est pas incorrecte mais vous devez être clair que le "tri" des indices non clusterisés et clusterisés est logique et non physique. Si vous lisez les pages au niveau feuille en suivant la liste chaînée et lisez les lignes de la page dans l'ordre du tableau d'emplacements, vous lirez les lignes d'index dans l'ordre trié mais physiquement les pages peuvent ne pas être triées. La croyance courante selon laquelle avec un index clusterisé les lignes sont toujours stockées physiquement sur le disque dans le même ordre que la clé d' indexation est fausse.
Ce serait une mise en œuvre absurde. Par exemple, si une ligne est insérée au milieu d'une table de 4 Go, SQL Server n'a pas à copier 2 Go de données dans le fichier pour faire de la place pour la ligne nouvellement insérée.
Au lieu de cela, un fractionnement de page se produit. Chaque page au niveau feuille des index cluster et non cluster a l'adresse ( File:Page
) de la page suivante et précédente dans l'ordre de clé logique. Ces pages n'ont pas besoin d'être contiguës ou dans un ordre clé.
Par exemple, la chaîne de page liée peut être 1:2000 <-> 1:157 <-> 1:7053
Lorsqu'un fractionnement de page se produit, une nouvelle page est allouée de n'importe où dans le groupe de fichiers (à partir d'une étendue mixte, pour les petites tables, ou d'une étendue uniforme non vide appartenant à cet objet ou d'une étendue uniforme nouvellement allouée). Cela pourrait même ne pas être dans le même fichier si le groupe de fichiers en contient plusieurs.
Le degré de différence entre l'ordre logique et la contiguïté de la version physique idéalisée est le degré de fragmentation logique.
Dans une base de données nouvellement créée avec un seul fichier, j'ai exécuté ce qui suit.
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
Puis vérifié la mise en page avec
SELECT page_id,
X,
geometry::Point(page_id, X, 0).STBuffer(1)
FROM T
CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
ORDER BY page_id
Les résultats étaient partout. La première ligne dans l'ordre des touches (avec la valeur 1 - mise en évidence avec la flèche ci-dessous) était sur presque la dernière page physique.
La fragmentation peut être réduite ou supprimée en reconstruisant ou en réorganisant un index pour augmenter la corrélation entre l'ordre logique et l'ordre physique.
Après avoir couru
ALTER INDEX ix ON T REBUILD;
J'ai le suivant
Si la table n'a pas d'index cluster, elle est appelée un tas.
Les index non clusterisés peuvent être construits sur un segment de mémoire ou un index clusterisé. Ils contiennent toujours un localisateur de ligne sur la table de base. Dans le cas d'un segment de mémoire, il s'agit d'un identificateur de ligne physique (rid) et se compose de trois composants (File: Page: Slot). Dans le cas d'un index cluster, le localisateur de ligne est logique (la clé d'index cluster).
Dans ce dernier cas, si l'index non groupé inclut déjà naturellement la ou les colonnes de clé CI sous forme de colonnes de clé NCI ou de INCLUDE
colonnes -d, rien n'est ajouté. Sinon, la ou les colonnes de clés CI manquantes sont ajoutées silencieusement au NCI.
SQL Server garantit toujours que les colonnes clés sont uniques pour les deux types d'index. Le mécanisme dans lequel cela est appliqué pour les index non déclarés comme uniques diffère cependant entre les deux types d'index.
Les index clusterisés sont uniquifier
ajoutés pour toutes les lignes avec des valeurs clés qui dupliquent une ligne existante. Ceci est juste un entier croissant.
Pour les index non cluster non déclarés comme uniques, SQL Server ajoute silencieusement le localisateur de ligne à la clé d'index non cluster. Cela s'applique à toutes les lignes, pas seulement à celles qui sont en fait des doublons.
La nomenclature clusterisée vs non clusterisée est également utilisée pour les index de magasin de colonnes. Le papier Améliorations apportées à la colonne SQL Server stocke les états
Bien que les données du magasin de colonnes ne soient pas vraiment "en cluster" sur aucune clé, nous avons décidé de conserver la convention SQL Server traditionnelle de faire référence à l'index principal comme un index en cluster.