我想在sql server中删除基于数据的300万个数据。我正在使用一个非常简单的查询和批量删除文件但该命令正在执行并且仍然运行超过3个小时。这种低性能的可能原因可能是什么。请找到我正在使用的代码
Create PROC [dbo].[DeleteOneWeekOldData]
@StartDate DateTime,
@EndDate DateTime
AS
DECLARE @continue INT
DECLARE @rowcount INT
SET @continue = 1
WHILE @continue = 1
BEGIN
SET ROWCOUNT 1000
BEGIN TRANSACTION
DELETE FROM WorkflowContentDetails WHERE StartDateTime BETWEEN @StartDate AND @EndDate
SET @rowcount = @@rowcount
COMMIT
IF @rowcount = 0
BEGIN
SET @continue = 0
END
END
GO
答案 0 :(得分:3)
您的查询存在两个问题。
SET ROWCOUNT 1000
导致数据以非常小的块被删除。如果需要删除1M行,那将是1000次删除操作。与大量小型操作相比,SQL Server将更好地处理少量大型操作。此外,SET ROWCOUNT
将不再影响将来版本中的插入/更新/删除操作。
StartDateTime BETWEEN @StartDate AND @EndDate
。如果该字段上没有索引,则可能需要很长时间。而不是那样,最好首先从主键列中选择值(如果你有一个,如果有(聚集的)索引定义在它上面)到临时表中然后在循环中工作 - 条件为索引列它的工作速度会快几倍。
答案 1 :(得分:3)
在这种情况下,您的最佳性能是按日期对表进行分区,然后在不再需要时截断或删除分区(而不是使用DELETE语句)。
性能提升的原因是:
1)通过指定要截断的分区,根据定义,您还定义了日期范围,因此无论是使用基于索引的检索还是使用表扫描,SQL Server都不需要寻找它,其中任何一个都需要时间。
2)TRUNCATE操作是DDL,而不是像DELETE这样的DML,因此操作不会写入事务日志,因此速度更快。它也没有填充日志文件的风险。 (当然,这可能会对增量备份和复制产生影响,如果您正在使用其中任何一种。)
在过去,我看到TRUNCATE操作在不到一分钟的时间内完成,相应的DELETE需要几个小时。
此处提供了该策略的演练: http://www.galaxysql.com/2013/09/sql-server-partitioning-for-performance-and-archiving/
答案 2 :(得分:1)
试试这个,为什么r使用循环?目的?
Create PROC [dbo].[DeleteOneWeekOldData]
@StartDate DateTime,
@EndDate DateTime
AS
begin
Set NoCount on
DECLARE @continue INT
DECLARE @rowcount INT
Declare @err int
--SET @continue = 1 --why ar u using these commented part
--WHILE @continue = 1
--BEGIN
-- SET ROWCOUNT 1000
BEGIN TRANSACTION
DELETE FROM WorkflowContentDetails WHERE StartDateTime BETWEEN @StartDate AND @EndDate
SET @err = @@Error
if(@err<>0)
COMMIT
else
rollback
END
GO