Does SQL Server use pointers instead of storing duplicate rows?
It depends on SQL Server's version and data compression options:
- Starting from SQL Server 2008, there is a compression option at row or page level.
- Page level compression uses many algorithms/techniques for compression. Regarding your question (pointers for duplicated data), page compression uses (also) prefix compression and dictionary compression:
Prefix Compression [...]The repeated prefix values in the column are
replaced by a reference to the corresponding prefix [...]
Dictionary Compression After prefix compression has been completed,
dictionary compression is applied. Dictionary compression searches for
repeated values anywhere on the page, and stores them in the CI area.
Unlike prefix compression, dictionary compression is not restricted to
one column. Dictionary compression can replace repeated values that
occur anywhere on a page. The following illustration shows the same
page after dictionary compression.
So, for prefix and dictionary compression (page compression), SQL Server uses pointers to store (partially or fully) duplicated values (not duplicated rows) within same column or within diff. columns.
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
Results:
PageCount_Person1_Uncompressed
------------------------------
53
PageCount_Person2_Compressed
----------------------------
2