我正在编写一个过程来删除n天以上的几个表中的所有行.
一个死的简单查询很容易编写
DELETE FROM [myTable] WHERE [Created] < GETDATE()-30
一个问题是日期字段上没有索引 – 我可以添加一个,但我正在通过执行以下操作来解决它:
SELECT @var = MAX([ID]) FROM myTable WHERE Created < GETDATE()-30; DELETE FROM myTable WHERE ID < @var
这看起来像是一种可接受的方法吗?
在一个(稍微慢一点)的测试服务器上运行它需要一个小时左右,并从其他进程中读取/写入它来杀死该表.
我不介意花一些时间来运行(虽然更快更好) – 但我不能让它在运行时锁定表一小时,因为有持续的读/写正在进行(主要是写) .
我的DB知识非常基础,因为我是编码器而不是dba.
有人能给我一个很好的方法来执行这项任务 – 以最有效的方式.
解决方法
您正在寻找的是基于分区的滑动窗口:
How to Implement an Automatic Sliding Window in a Partitioned Table on SQL Server 2005.按日对表进行分区,您可以在午夜的单个分区切换操作中有效地停止一整天.分区开关基本上是瞬时的.
如果你想要一个开销略低的解决方案(分区会产生严重的后果并在整个应用程序中产生波动,特别是当索引必须对齐时,这是快速切换操作的要求),那么你必须按照设计来设计你的模式.这个操作.有99.99%的置信度,我可以说myTable最左边的聚类键必须是Created字段.这将允许有效的批量删除(从myTable删除top(2500)Created< ...).您希望对其进行批处理的原因有很多(一次最多2500个),最重要的是您必须避免锁定升级,并且必须将任何单个事务的大小保持在合理的限制范围内.