Jac*_*rys 3 sql-server-2005 sql-server delete transaction-log
我有多个表备份了数据,现在暂时删除旧数据,由于空间限制,目前无法选择存档。我试过运行以下命令:
WHILE 1 = 1
BEGIN
DELETE TOP ( 4000 )
FROM [OLD_TABLE] WITH (TABLOCKX)
WHERE [Date] < '2014-01-01 00:00:00'
IF @@ROWCOUNT = 0
BREAK
END
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但非常缓慢……比如 17 多个小时,并且只删除了约 140,000 行。
这里的关键是这张表,其他需要减少的表非常大,大约有 50-6000 万行,大约有 16-17 GB 的空间。物理磁盘上只剩下 20 GB 的空间。我已经考虑将我想要保留的数据放在中间表中,截断和重新填充,但我担心在这些操作完成时我们会用完磁盘上的空间。这是一个生产数据库。我继承了这个烂摊子,我正在尝试清理它并试图清理这个数据库,这样我们就可以保持功能,直到我们可以安装新硬件。
是否有任何我(数据库管理的相对新手)没有遇到过的方法可以让我以更快、更有效的方式执行此操作?
*表名和列名已匿名。
编辑
就目前情况而言,查询:
DELETE TOP (4000)
FROM [OLD_TABLE] WITH (TABLOCKX)
WHERE [Date] < '2014-01-01 00:00:00'
Run Code Online (Sandbox Code Playgroud)
...必须扫描整个堆表,测试它找到的每一行,直到最终找到要删除的 4000 行。在下一次迭代中,整个业务又从第一个开始。假设每次扫描过程都以相同的(分配单元)顺序执行,随着时间的推移,这些扫描将花费越来越长的时间才能找到 4000 行。
在[Date]
列上创建索引将允许 SQL Server 更有效地查找 4000 行。它确实为每次删除增加了少量开销(因为新的非聚集索引也需要维护),但这与不每次执行扫描所节省的工作量相比,这算不了什么。索引也需要一定的空间,但不能太大。在恢复数据删除过程之前,您应该创建以下索引:
CREATE NONCLUSTERED INDEX <index_name>
ON dbo.OLD_TABLE ([Date]);
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果数据库启用了快照隔离或读提交快照隔离(即使没有主动使用!),TABLOCKX
提示将不足以确保释放空堆页面。因此,您的堆表可能包含许多空页——这是一个问题,因为您的空间太少了。
解决此空间管理问题的标准方法是创建聚集索引(或发出ALTER TABLE REBUILD
语句,但这需要 SQL Server 2008)。由于空间限制,创建聚集索引似乎也不适合您。考虑到空间问题,目前还没有明显的方法来解决这个问题。
在删除过程中要注意的一件事是事务日志使用的空间。如果数据库正在恢复FULL
或正在BULK_LOGGED
恢复,您将需要随时备份日志。如果数据库正在使用SIMPLE
恢复,您可能需要CHECKPOINT
不时发布手册以释放事务日志空间以供重用(否则物理文件可能会增长)。
如果您可以获得一些额外的临时存储,更好的方法可能是将要保留的数据批量导出到安全位置,删除表,重新创建它(最好使用聚集索引!)并重新加载保存的数据。这通常比增量删除过程快,但这取决于您的目标和优先级。
归档时间: |
|
查看次数: |
147 次 |
最近记录: |