SQL Server是否使用指针而不是存储重复的行?


8

sp_spaceused在我们的软件中执行操作之前和之后,我正在使用内置的存储过程,以查看哪些表具有行插入以及每个表的大小如何变化。

我所看到的是,在所有向其写入行的表中,只有极少数的情况表明该表在一侧增加了。显示行已添加的其他行显示此存储过程的大小没有变化。

这是唯一的不正确的情况是在对所有表执行截断后的第一个事务上。因此,对我来说,似乎SQL Server在存储重复数据时显示的是插入行,但必须仅存储指向先前相同行的指针。

有人可以确认吗?


被判dba.se
GBN

Answers:


13

否,SQL Server无法检测到重复的行

SQL Server正在填充分配的页面内的空白页面或部分空白页面。

因此,如果我的行很窄(例如2列),则可以在同一页上添加几百行而不增加使用的空间。

快速而肮脏的演示(没有重复的行,但是您可以根据需要进行操作)

IF OBJECT_ID('dbo.Demo') IS NOT NULL
    DROP TABLE dbo.Demo;
GO
CREATE TABLE dbo.Demo (DemoID int NOT NULL IDENTITY(1,1), Demo char(1) NOT NULL)
GO
SELECT 'zero rows, zero space', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

INSERT dbo.Demo VALUES ('a');
GO
SELECT 'one row. Peanuts', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

INSERT dbo.Demo VALUES ('b');
GO 100
SELECT '101 rows. All on one page', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

INSERT dbo.Demo VALUES ('b');
GO 1899
SELECT '2000 rows. More than one page', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

TRUNCATE TABLE dbo.Demo
GO
SELECT 'zero rows, zero space. TRUNCATE deallocates pages', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

INSERT dbo.Demo VALUES ('c');
GO 500
SELECT '500 rows. Some space used', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

DELETE dbo.Demo
GO
SELECT 'zero rows after delete. Space still allocated', SUM(ps.reserved_page_count)/128.0 AS ReservedMB, SUM(ps.used_page_count)/128.0 AS UsedMB
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id = OBJECT_ID('dbo.Demo')
GO

IF OBJECT_ID('dbo.Demo') IS NOT NULL
    DROP TABLE dbo.Demo;
GO

谢谢多数民众赞成在这样一个美妙的答案。希望我能投票更多。也许您还可以建议,如果您愿意的话,我将如何计算页面中使用的实际数据。我只能看到:名称行保留数据index_size未使用费用6 16 KB 8 KB 8 KB 0 KB从这里我看不到我的6行使用了多少页面。告诉我,即使我知道并非如此,该页面中仍未使用0KB。

我已经尝试过DBCC SHOWCONTIG,但是据我了解,这并不显示存储在LOB中的大列。

想通了,我会发表评论而不是提出新的问题...存储更宽的表如何工作?例如,如果我有一个非常宽的表,但大多数情况下60%左右的列为空,会发生什么情况?我假设该行将在页面中存储相同数量的空间,因为那些列可能有数据?仅就存储而言(当然,任何事情都可以用文字来表示),最好有更多的窄表?如果最终还是需要经常拉入“空”列,那么将其与主表保持在一起可能很有意义?
bdwakefield 2014年

7

SQL Server是否使用指针而不是存储重复的行?

它取决于SQL Server的版本和数据压缩选项:

  • 从SQL Server 2008开始,在行或页面级别提供压缩选项。
  • 页面级压缩使用许多算法/技术进行压缩。关于您的问题(重复数据的指针),页面压缩还使用 前缀压缩和字典压缩

前缀压缩 [...]列中的重复前缀值被对相应前缀的引用替换。

字典压缩完成前缀压缩后,将应用字典压缩。字典压缩在页面上的任何位置搜索重复的值,并将其存储在CI区域中。与前缀压缩不同,字典压缩不限于一列。字典压缩可以替换页面上任何地方出现的重复值。下图显示了字典压缩后的同一页面。

因此,对于前缀和字典压缩(页面压缩),SQL Server使用指针在同一列或差异内存储 (部分或全部)重复的(不重复的行)。列。

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

结果:

PageCount_Person1_Uncompressed
------------------------------
53

PageCount_Person2_Compressed
----------------------------
2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.