为什么删除小数列不会释放任何空间?

Rit*_*kre 5 sql-server disk-space

我有几个表,每个表都有几列数据类型为十进制的列。我决定删除这些列以释放一些空间。我使用ALTER TABLE DROP COLUMN col1了相同的命令。但是,我无法查看正在释放的任何空间。为什么会这样,因为 Decimal 不是可变长度列,应该立即释放空间?

附注。这是我用来跟踪可用空间量的查询:

SELECT
b.groupname AS 'File Group',
Name,
[Filename],
CONVERT (Decimal(15,2),ROUND(a.Size/128.000,2)) [Currently Allocated Space (MB)],
CONVERT (Decimal(15,2),ROUND(FILEPROPERTY(a.Name,'SpaceUsed')/128.000,2)) AS [Space Used (MB)],
CONVERT (Decimal(15,2),ROUND((a.Size-FILEPROPERTY(a.Name,'SpaceUsed'))/128.000,2)) AS [Available Space (MB)],
'DBCC SHRINKFILE ('''+Name+''','+CAST(CONVERT (Decimal(15,2),ROUND((FILEPROPERTY(a.Name,'SpaceUsed'))/128.000,2)) AS VARCHAR(10))+')' QUERY
FROM dbo.SYSFILES a (NOLOCK)
JOIN SYSFILEGROUPS b (NOLOCK)
ON a.groupid = b.groupid
ORDER BY b.groupname
Run Code Online (Sandbox Code Playgroud)

Joe*_*ish 8

对于行存储表,您不应期望删除列操作会释放任何空间。数据以行格式存储在页面上。我有点过于简单化了,但是对于大多数行存储表,您最终会在单个页面上存储许多行。

考虑如果删除一列,页面会发生什么。您最终会得到可以返回给 SQL Server 的任何完全空白的页面吗?不,相反,您会在页面上看到一堆小“洞”。除非您对表进行维护操作,否则 SQL Server 不会给您任何空间。例如,重建表会将所有数据复制到新页面中。这应该会减少删除列后表所需的空间。

行存储演示

这是行存储的一个简单演示,其中删除列仅REBUILD在表上完成后释放空间:

CREATE TABLE [dbo].[X_TBL_159269](
       [NUM] [int] NOT NULL,
       [COL1] decimal(18,0) NULL,
       [COL2] decimal(18,0) NULL,
       [COL3] decimal(18,0) NULL,
CONSTRAINT [PK_X_TBL_159269] PRIMARY KEY CLUSTERED
(
       [NUM] ASC
)
);

-- insert 1000000 rows
WITH
       L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
       L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
       L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
       L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
       L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
       L5 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L4 B),
       NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L5)
       INSERT INTO [X_TBL_159269] WITH (TABLOCK)
       SELECT TOP (1000000) NUM, NUM AS [COL1], NUM AS [COL2],  NUM AS [COL3]
       FROM NUMS
       ORDER BY NUM;

sp_spaceused 'X_TBL_159269';
Run Code Online (Sandbox Code Playgroud)
/*
保留数据 index_size 未使用
39752 KB 39608 KB 80 KB 64 KB
*/
ALTER TABLE [X_TBL_159269] DROP COLUMN COL2;

sp_spaceused 'X_TBL_159269';
Run Code Online (Sandbox Code Playgroud)
/*
保留数据 index_size 未使用
39752 KB 39608 KB 80 KB 64 KB
*/
-- rebuild clustered index to free up space
ALTER TABLE [X_TBL_159269] REBUILD;
    
sp_spaceused 'X_TBL_159269';
Run Code Online (Sandbox Code Playgroud)
/*
保留数据 index_size 未使用
30728 KB 30656 KB 72 KB 0 KB
*/

列存储演示

对于列存储表,数据以列格式存储。删除一列将立即释放空间:

DROP TABLE IF EXISTS [dbo].[X_TBL_159269];

CREATE TABLE [dbo].[X_TBL_159269](
       [NUM] [int] NOT NULL,
       [COL1] decimal(18,0) NULL,
       [COL2] decimal(18,0) NULL,
       [COL3] decimal(18,0) NULL,
       INDEX cci CLUSTERED COLUMNSTORE
);

-- insert 1000000 rows
WITH
       L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
       L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
       L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
       L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
       L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
       L5 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L4 B),
       NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L5)
       INSERT INTO [X_TBL_159269] WITH (TABLOCK)
       SELECT TOP (1000000) NUM, NUM AS [COL1], NUM AS [COL2],  NUM AS [COL3]
       FROM NUMS
       ORDER BY NUM
       OPTION (MAXDOP 1);

sp_spaceused 'X_TBL_159269';
Run Code Online (Sandbox Code Playgroud)
/*
保留数据
10760 KB   10672 KB
*/
ALTER TABLE [X_TBL_159269] DROP COLUMN COL2;

sp_spaceused 'X_TBL_159269';
Run Code Online (Sandbox Code Playgroud)
/*
保留数据
8200 KB    8008 KB
*/