DBCC CLEANTABLE不会释放已用空间

时间:2016-04-05 09:07:29

标签: sql sql-server tsql sql-server-2012 dbcc

我有大约300个表,每个表有5.5kk行。其中一行使用nvarchar(128)作为数据类型(SQL Server 2012) 我们决定将其更改为int并将FK添加到包含所有nvarchars的字典表中。

完成所有操作后,我删除了nvarchar列,但表的大小保持不变。 我使用DBCC CLEANTABLE并重建索引以回收可用空间,但表的大小仍未改变。

到目前为止,我找到的唯一方法是将所有数据复制到新表中。

问题:我在这里缺少什么?为什么空间仍被标记为已使用且我无法释放是通过缩小或CREANTABLE命令?

谢谢!

答案:看起来答案非常简单,由于我缺乏知识,我无法找到答案。 这里的主要问题是堆碎片。这个查询对我有用:

ALTER TABLE [TABLE_NAME] REBUILD

我不确定这是最好的方式,但至少它是一个有效的方式。

Edited1 : 对不起,我想我忘了提 - 我在Text字段上有聚集索引,所以我不得不删除索引才能真正删除该字段。现在我没有索引。

Edited2

老桌子:

CREATE TABLE [dbo].[Data_](
    [ID] [bigint] PRIMARY KEY IDENTITY(1,1) NOT NULL,
    [Text] [nvarchar](128) NOT NULL,
    [Category] [tinyint] NOT NULL,
    [Country] [nvarchar](2) NOT NULL,
    [ImportTimestamp] [date] NOT NULL
)

新表:

CREATE TABLE [dbo].[Data_New](
    [ID] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL,
    [Category] [tinyint] NOT NULL,
    [Country] [nvarchar](2) NOT NULL,
    [TextID] [int] NOT NULL)

ALTER TABLE [dbo].[Data_New]  WITH CHECK ADD FOREIGN KEY([TextID])
REFERENCES [dbo].[Dictionary] ([Id])

复制脚本:

INSERT INTO Data_New
      ([Category]
      ,[Country]
      ,[TextID])
SELECT 
      [Category]
      ,[Country]
      ,[TextID]
  FROM Data_

2 个答案:

答案 0 :(得分:2)

您是否确定因为此列更改而导致表格变小? nvarchar(128)并不意味着SQL Server将分配128个字节(+2)来保存数据,例如字符串' test'。字符串'测试'只需要6个字节。也许您需要先检查表中的可用空间:

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME = 'TABLE_NAME'
    AND t.is_ms_shipped = 0'
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name

答案 1 :(得分:1)

如果您不关心理解问题并且只是想摆脱它,那么重建索引是消除任何浪费的可靠方法。这是因为索引重建新建了物理数据结构。无论旧索引包含什么都不重要。

将此与CLEANTABLE进行比较时需要权衡利弊。如果重建为你完成了这项工作,我总是这样做,因为它是一个完整的解决方案。

当我说" index"在这个答案中,我的意思是包含您关注的一个列的所有物理结构。这可以是b-tree索引或表所基于的堆。