释放未使用的空间 SQL Server 表

Der*_*nch 11 sql-server sql-server-2012

我在 SQL Server 2012 Express 中有一个表,有很多未使用的空间。

我需要释放数据库中的空间。

| 姓名 | 行 | 保留 | 数据 | INDEX_SIZE | 未使用 |
|-------------|--------|--------------|----------- ---|------------|--------------|
| 我的表名 | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 KB |

如何让 SQL 释放 3165104KB?

我已经试过了:

Alter table MyTableName Rebuild
DBCC CLEANTABLE (MyDbName,"MyTableName ", 0)
ALTER INDEX ALL ON MyTableName REORGANIZE ; 
ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF) 
Run Code Online (Sandbox Code Playgroud)

这是表:

CREATE TABLE [dbo].[MyTableName](
    [ImageID] [int] IDENTITY(1,1) NOT NULL,
    [DateScan] [datetime] NULL,
    [ScanImage] [image] NULL,
 CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED 
(
    [ImageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

我们所做的唯一一件事就是ScanImage用一个更小的图像替换每一行(这是有多少未使用的空间)。

Mar*_*ith 10

我们所做的唯一一件事是ScanImage用一个更小的图像替换每一行(这是有多少未使用的空间)

通过进行一些实验,最节省空间的方法是删除分配单元并重新填充它(如果您有一个维护窗口来执行此操作)。

使用问题中的表结构为我实现最佳空间减少的示例代码是:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;

BEGIN TRAN

SELECT [ImageID],
       [ScanImage]
INTO   #Temp
FROM   [dbo].[MyTableName]

ALTER TABLE [dbo].[MyTableName]
  DROP COLUMN [ScanImage]

/*Allocation unit not removed until after this*/
ALTER INDEX PK_Image ON MyTableName REBUILD

ALTER TABLE [dbo].[MyTableName]
  ADD [ScanImage] IMAGE NULL

UPDATE [dbo].[MyTableName]
SET    [ScanImage] = T.[ScanImage]
FROM   [dbo].[MyTableName] M
       JOIN #Temp T
         ON M.ImageID = T.[ImageID]

DROP TABLE #Temp

COMMIT 
Run Code Online (Sandbox Code Playgroud)

一切都在事务中,因此如果机器崩溃,它将被回滚。可能可以做一些错误处理或至少SET XACT_ABORT ON。我曾经SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;防止在复制期间或之后发生任何并发修改并丢失。

减少image所有行的大小后保留的LOB页数如下:

+------------------------------------------------- -+---------------------+-------------------------+
| 活动 | lob_used_pa​​ge_count | lob_reserved_pa​​ge_count |
+------------------------------------------------- -+---------------------+-------------------------+
| 插入 10,000 行,每行 100,000 字节数据 | 135005 | 135017 |
| 将所有行更新为 10,000 字节图像数据 | 31251 | 135012 |
| 重组 | 23687 | 25629 |
| 删除并重新添加图像数据 | 13485 | 13489 |
+------------------------------------------------- -+---------------------+-------------------------+


Han*_*non 6

尝试

ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF)

这将重新创建聚集索引,因此您将需要在数据库中留出额外空间来完成操作。如果由于磁盘已满而没有任何额外空间,则可以向数据库(在不同磁盘上)添加一个新数据文件并将表移动到该数据库中。

也可能使用小于 100% 的 FILLFACTOR 定义聚集索引。将填充因子设置为例如 66%,将使每个数据页的 1/3 留空以备将来使用。如果这是问题,您可以使用修改填充因子ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)

如果您最近从表中删除了可变长度字段,您也可以尝试 DBCC CLEANTABLE( Databasename, "MyTableName")

在线书籍 (BOL) 在http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx上有一篇关于重建索引的精彩文章