【问题标题】:SQL Index Space Does Not Decrease After Deleting Data From Table从表中删除数据后 SQL 索引空间不减少
【发布时间】:2015-12-20 00:28:13
【问题描述】:

我最近尝试清理一张桌子。该表有 40GB 大,索引空间为 400MB。从表中删除大量记录后,它减少到4GB,但索引空间仍然在400MB左右。我认为可能是因为删除记录时索引碎片,然后我重建索引,但索引空间仍然是398MB。我不明白,如果表大小减少了 10 倍,为什么索引空间没有按比例减少?

索引的构建

ALTER TABLE [CADIS_PROC].[DC_UPPREBBO_INFO_VALUE] 
ADD PRIMARY KEY CLUSTERED ( 
[CADIS_ID] ASC, 
[SOURCE] ASC, 
[SOURCE_KEY] ASC, 
[FILE_DATE] ASC )WITH 
(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO

重建索引的脚本

ALTER INDEX IndexName ON Schema.Table
REBUILD;
GO

我如何检查索引碎片,我也右键单击表并查看它的属性,它显示了表和索引空间的大小。

SELECT index_id, name, avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID(), NULL, NULL, NULL)

该索引是表上唯一的索引,它占碎片的 0.8%。

【问题讨论】:

  • 当你说你重建了索引时,你到底是怎么做到的?您还可以提供有关索引的任何详细信息,因为这也会有所帮助。
  • 索引创建如下ALTER TABLE [CADIS_PROC].[DC_UPPREBBO_INFO_VALUE] ADD PRIMARY KEY CLUSTERED ( [CADIS_ID] ASC, [SOURCE] ASC, [SOURCE_KEY] ASC, [FILE_DATE] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO我使用SQL管理工作室的选项重建索引link
  • 您是否还可以包含用于报告空间使用情况的命令。顺便说一句,您可能还想编辑原始问题以提供此信息。

标签: sql-server indexing database-performance sqlperformance


【解决方案1】:

聚集索引表。表的数据是按照聚集索引定义的顺序物理存储的。

如果表只有聚集索引而没有非聚集索引,我预计索引空间几乎为零。

我有一个只有聚集索引的表。 SSMS 显示:

Data space  = 3,215.539 MB
Index space = 5.211 MB       (not zero, but pretty close)

系统每晚都使用以下命令重建索引:

ALTER INDEX ALL ON <table name> REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = OFF, SORT_IN_TEMPDB = ON )

尝试它而不是指定索引名称。

要测量表使用的磁盘空间,请尝试使用sp_spaceused。 它有一个参数@updateusage,可能有用。

尝试像这样运行这个过程:

EXEC sp_spaceused @objname = N'[dbo].[TableName]', @updateusage = N'TRUE'

关于这个存储过程的 MSDN 文章有这样的注释:

当您删除或重建大型索引,或者删除或截断大型索引时 表,数据库引擎延迟实际的页面释放,以及 它们关联的锁,直到事务提交之后。延期 删除操作不会立即释放分配的空间。所以, sp_spaceused 在删除后立即返回的值或 截断大对象可能无法反映实际磁盘空间 可用的。有关延迟分配的更多信息,请参阅 删除和重建大型对象。

也可以查看相关文章Dropping and Rebuilding Large Objects

【讨论】:

    【解决方案2】:

    意识到与非聚集索引不同,聚集索引是使用实际数据页构建的。可能值得尝试删除然后重新创建索引,而不是使用 REBUILD 来查看它有什么效果。

    引自MSDN here

    减少索引中的碎片

    当索引以碎片化的方式碎片化时 影响查询性能,有三种选择减少 碎片化:

    1. 删除并重新创建聚集索引。

    重新创建聚集索引会重新分配数据并导致 完整的数据页。可以使用 CREATE INDEX 中的 FILLFACTOR 选项。这种方法的缺点是 索引在删除和重新创建周期中处于脱机状态,并且 该操作是原子的。如果索引创建中断, 不会重新创建索引。有关详细信息,请参阅创建索引 (Transact-SQL)。

    1. 使用 ALTER INDEX REORGANIZE(DBCC INDEXDEFRAG 的替代品)来 按逻辑顺序重新排序索引的叶级页面。 因为这是在线操作,所以索引可用,而 语句正在运行。操作也可以不中断 失去工作已经完成。这种方法的缺点是它 在重组数据方面不如重建索引做得好 操作,并且它不更新统计信息。重新排序的叶级页面 按逻辑顺序排列索引。

    2. 使用 ALTER INDEX REBUILD(DBCC DBREINDEX 的替代品)来重建 在线或离线索引。有关详细信息,请参阅更改 索引 (Transact-SQL)。

    您已经尝试过 #3,如果可行,您可能需要考虑 1 或 2 来衡量它们的效果。如果您只是想了解观察到的行为,请在可以重建其数据库的开发/测试服务器上使用数据库副本(或至少相关表)。此外,您可能还想尝试使用非聚集索引来进行比较。

    就我个人而言,我一直对任何报告工具对聚集索引的索引性能和空间利用率表示怀疑,因为它们必须区分索引和共享相同分配空间的数据。

    【讨论】:

    • 我也尝试过重组,我读了一些test 说在聚集索引上删除和重新创建与重建没有区别。我不明白的是为什么当我删除行时索引空间没有与实际表大小的减少成比例地减少,而索引没有碎片。
    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    相关资源
    最近更新 更多