Dans le stockage orienté ligne de SQL Server, les index groupés et non groupés sont organisés sous forme d'arbres B.
( Source d'image )
La principale différence entre les index en grappes et les index non en grappes est que le niveau de feuille de l'index en grappes es la table. Cela a deux implications.
- Les lignes des pages feuilles de l'index en grappe contiennent toujours quelque chose pour chacune des colonnes (non éparses) du tableau (soit la valeur, soit un pointeur vers la valeur réelle).
- L'index clusterisé est la copie primaire d'une table.
Les index non clusterisés peuvent aussi faire le point 1 en utilisant la fonction INCLUDE
(depuis SQL Server 2005) pour inclure explicitement toutes les colonnes non clés, mais il s'agit de représentations secondaires et il existe toujours une autre copie des données (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 les valeurs des colonnes clés A, B
et les pages de niveau feuille contenant A, B, C, D
Il ne peut y avoir qu'un seul index clusterisé par table, parce que les lignes de données ne peuvent être triées que dans un seul ordre.
La citation ci-dessus, tirée des livres en ligne sur le serveur SQL, est source de confusion.
À mon avis, il serait bien mieux formulé comme suit .
Il ne peut y avoir qu'un seul index clusterisé par table car les lignes de niveau feuille de l'index clusterisé sont les lignes du tableau.
La citation en ligne du livre n'est pas incorrecte mais il faut bien comprendre que le "tri" des index non groupés et groupés est logique et non physique. Si vous lisez les pages au niveau des feuilles en suivant la liste chaînée et que vous lisez les lignes de la page dans l'ordre du tableau des fentes, vous lirez les lignes de l'index dans l'ordre trié, mais physiquement, les pages peuvent ne pas être triées. L'idée communément admise qu'avec un index en cluster, les lignes sont toujours stockées physiquement sur le disque dans le même ordre que l'index. clé 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, le serveur SQL fait ce qui suit pas doit copier 2 Go de données plus haut dans le fichier pour faire de la place à la nouvelle ligne insérée.
Au lieu de cela, une division de la page se produit. Chaque page au niveau des feuilles des index groupés et non groupés a l'adresse ( File: Page
) de la page suivante et précédente dans l'ordre logique des clés. Ces pages ne doivent pas nécessairement être contiguës ou dans l'ordre des clés.
Par exemple, la chaîne de pages liées pourrait être la suivante 1:2000 <-> 1:157 <-> 1:7053
Lorsqu'une division de page se produit, une nouvelle page est allouée à partir de n'importe quel endroit du groupe de fichiers (soit à partir d'une étendue mixte, pour les petites tables, soit à partir d'une étendue uniforme non vide appartenant à cet objet, soit à partir d'une étendue uniforme nouvellement allouée). Cela peut même ne pas être dans le même fichier si le groupe de fichiers en contient plusieurs.
Le degré auquel l'ordre logique et la contiguïté diffèrent 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 j'ai 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 sont très variables. La première ligne dans l'ordre des clés (avec la valeur 1 - mise en évidence par une flèche ci-dessous) se trouvait pratiquement sur 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 exécuté
ALTER INDEX ix ON T REBUILD;
J'ai obtenu ce qui suit
Si la table n'a pas d'index clusterisé, elle est appelée "heap".
Les index non clusterisés peuvent être construits sur un tas ou un index clusterisé. Ils contiennent toujours un localisateur de ligne qui renvoie à la table de base. Dans le cas d'un tas, il s'agit d'un identificateur de rangée physique (rid) et il se compose de trois éléments (File:Page : Slot). Dans le cas d'un index clusterisé, le localisateur de ligne est logique (la clé de l'index clusterisé).
Dans ce dernier cas, si l'index non clusterisé inclut déjà naturellement la ou les colonnes clés CI, soit en tant que colonnes clés NCI, soit en tant que colonnes clés NCI. INCLUDE
-d colonnes alors rien n'est ajouté. Dans le cas contraire, la ou les colonnes clés de l'ICN manquantes sont ajoutées à l'ICN en silence.
SQL Server s'assure toujours que les colonnes clés sont uniques pour les deux types d'index. Le mécanisme par lequel cela est appliqué pour les index non déclarés comme uniques diffère cependant entre les deux types d'index.
Les index en grappe obtiennent un uniquifier
ajoutées pour toutes les lignes dont les valeurs de clé font double emploi avec une ligne existante. Il s'agit simplement d'un nombre entier ascendant.
Pour les index non clusterisés qui ne sont pas déclarés comme uniques, SQL Server ajoute silencieusement le localisateur de ligne dans la clé de l'index non clusterisé. Cela s'applique à toutes les lignes, et pas seulement à celles qui sont réellement des doublons.
La nomenclature clustered vs non clustered est également utilisée pour les index de type column store. Le papier Améliorations des magasins de colonnes du serveur SQL États
Bien que les données du stockage en colonnes ne soient pas réellement "groupées" sur une clé, nous avons décidé de conserver la convention traditionnelle de SQL Server qui consiste à faire référence aux données du stockage en colonnes. nous avons décidé de conserver la convention traditionnelle de SQL Server qui fait l'index primaire comme un index clusterisé.
2 votes
Ces deux vidéos ( Structures d'index groupés et non groupés dans SQL Server y Conception de bases de données 39 - Index (clusterisé, non clusterisé, index composite) ) sont, à mon avis, plus utiles qu'une réponse en texte clair.