O SQL Server usa ponteiros em vez de armazenar linhas duplicadas?
Depende da versão do SQL Server e das opções de compactação de dados:
- A partir do SQL Server 2008, há uma opção de compactação no nível da linha ou da página.
- A compactação no nível da página usa muitos algoritmos / técnicas para compactação. Em relação à sua pergunta (ponteiros para dados duplicados), a compactação de página usa (também) compactação de prefixo e compactação de dicionário :
Compactação do prefixo Os valores repetidos do prefixo na coluna são substituídos por uma referência ao prefixo correspondente.
Compactação de dicionário Após a compactação do prefixo, a compactação de dicionário é aplicada. A compactação do dicionário procura valores repetidos em qualquer lugar da página e os armazena na área de IC. Ao contrário da compactação de prefixo, a compactação de dicionário não está restrita a uma coluna. A compactação do dicionário pode substituir valores repetidos que ocorrem em qualquer lugar da página. A ilustração a seguir mostra a mesma página após a compactação do dicionário.
Portanto, para compactação de prefixo e dicionário (compactação de página), o SQL Server usa ponteiros para armazenar (parcialmente ou totalmente) valores duplicados (não linhas duplicadas) na mesma coluna ou no diff. colunas.
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
Resultados:
PageCount_Person1_Uncompressed
------------------------------
53
PageCount_Person2_Compressed
----------------------------
2