SQL Server utilise-t-il des pointeurs au lieu de stocker des lignes en double?
Cela dépend de la version de SQL Server et des options de compression des données:
- À partir de SQL Server 2008, il existe une option de compression au niveau de la ligne ou de la page.
- La compression au niveau de la page utilise de nombreux algorithmes / techniques de compression. Concernant votre question (pointeurs pour les données dupliquées), la compression de page utilise (également) la compression de préfixe et la compression de dictionnaire :
Compression de préfixe [...] Les valeurs de préfixe répétées dans la colonne sont remplacées par une référence au préfixe [...] correspondant
Compression du dictionnaire Une fois la compression du préfixe terminée, la compression du dictionnaire est appliquée. La compression du dictionnaire recherche les valeurs répétées n'importe où sur la page et les stocke dans la zone CI. Contrairement à la compression de préfixe, la compression de dictionnaire n'est pas limitée à une colonne. La compression du dictionnaire peut remplacer les valeurs répétées qui se produisent n'importe où sur une page. L'illustration suivante montre la même page après la compression du dictionnaire.
Ainsi, pour la compression de préfixe et de dictionnaire (compression de page), SQL Server utilise des pointeurs pour stocker (partiellement ou entièrement) les valeurs dupliquées (pas les lignes dupliquées) dans la même colonne ou dans diff. Colonnes.
CREATE DATABASE TestComp;
GO
USE TestComp;
GO
CREATE TABLE Person1 (
PersonID INT IDENTITY PRIMARY KEY,
FirstName NVARCHAR(100) NOT NULL,
LastName NVARCHAR(100) NOT NULL
);
GO
DECLARE
@f NVARCHAR(100) = REPLICATE('A',100),
@l NVARCHAR(100) = REPLICATE('B',100);
INSERT Person1 (FirstName, LastName)
VALUES (@f, @l);
GO 1000
CREATE TABLE Person2 (
PersonID INT IDENTITY PRIMARY KEY,
FirstName NVARCHAR(100) NOT NULL,
LastName NVARCHAR(100) NOT NULL
);
GO
ALTER TABLE Person2
REBUILD
WITH (DATA_COMPRESSION=PAGE);
GO
DECLARE
@f NVARCHAR(100) = REPLICATE('A',100),
@l NVARCHAR(100) = REPLICATE('B',100);
INSERT Person2 (FirstName, LastName)
VALUES (@f, @l);
GO 1000
SELECT f.page_count AS PageCount_Person1_Uncompressed
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('Person1'), 1, DEFAULT, DEFAULT) f
SELECT f.page_count AS PageCount_Person2_Compressed
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('Person2'), 1, DEFAULT, DEFAULT) f
GO
Résultats:
PageCount_Person1_Uncompressed
------------------------------
53
PageCount_Person2_Compressed
----------------------------
2