SQL Server utilizza i puntatori invece di archiviare righe duplicate?
Dipende dalla versione di SQL Server e dalle opzioni di compressione dei dati:
- A partire da SQL Server 2008, esiste un'opzione di compressione a livello di riga o di pagina.
- La compressione a livello di pagina utilizza molti algoritmi / tecniche per la compressione. Per quanto riguarda la tua domanda (puntatori per i dati duplicati), la compressione della pagina utilizza (anche) la compressione del prefisso e la compressione del dizionario :
Compressione prefisso [...] I valori di prefisso ripetuti nella colonna sono sostituiti da un riferimento al prefisso corrispondente [...]
Compressione del dizionario Al termine della compressione del prefisso, viene applicata la compressione del dizionario. La compressione del dizionario cerca valori ripetuti in qualsiasi punto della pagina e li memorizza nell'area CI. A differenza della compressione dei prefissi, la compressione del dizionario non è limitata a una colonna. La compressione del dizionario può sostituire i valori ripetuti che si verificano ovunque in una pagina. La seguente illustrazione mostra la stessa pagina dopo la compressione del dizionario.
Pertanto, per la compressione del prefisso e del dizionario (compressione della pagina), SQL Server utilizza i puntatori per archiviare (parzialmente o completamente) valori duplicati (non righe duplicate) all'interno della stessa colonna o all'interno di diff. colonne.
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
risultati:
PageCount_Person1_Uncompressed
------------------------------
53
PageCount_Person2_Compressed
----------------------------
2