【问题标题】:Delete large number of rows删除大量行
【发布时间】:2013-07-05 15:26:46
【问题描述】:

我想根据此标准从 Table1 中删除记录(行 > 3 亿条记录)(返回 > 1 亿条记录): Column1 IS NULL AND Column2 IS NULL AND Column3 IS NULL AND Column4 IS NULL AND Column5 IS NULL AND Column6 IS NULL AND Column7 IS NULL

表定义:

CREATE TABLE [dbo].[Table1](
    [ID] [uniqueidentifier] NOT NULL,
    [Column1] [float] NULL,
    [Column2] [float] NULL,
    [Column3] [float] NULL,
    [Column4] [float] NULL,
    [Column5] [float] NULL,
    [Column6] [float] NULL,
    [Column7] [float] NULL,
    [Table2ID] [uniqueidentifier] NULL, 
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

注意:Table2ID 是 Table2 的外键约束

CREATE TABLE [dbo].[Table2](
    [ID] [uniqueidentifier] NOT NULL,
    [Column1] [date] NULL,
    [Column2] [tinyint] NULL,
    [Column3] [tinyint] NULL,
 CONSTRAINT [PK_Table2_ID] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

我还想从 Table2 中删除所有在 Table1 中不再引用的孤立记录(行数约为 1000 万条记录)。以下是我采取的方法:

一个。使用 Table1ID 和 Table2ID 列创建临时表 #table1。捕获所有相关的 Table1ID 并运行以下删除查询。

Delete from Table1 where ID in (select Table1ID from #table1)

Delete from Table2 where ID in (select Table2ID from #table1)

上述查询可能由于表扫描而花费了大量时间。

b.一切都与上面相同,但在 #table1 中的 Table1ID 列上创建唯一聚集索引并在 Table2ID 上创建唯一索引并运行以下查询:

Delete from Table1 t1 join #table1 tmp1 on t1.ID=tmp1.Table1ID

Delete from Table2 t2 join #table1 tmp1 on t1.ID=tmp1.Table2ID

有没有更好的方法来处理这种情况?从 Table1 和 Table2 中删除记录的最佳方法是什么?

注意:我知道我们创建一个新表、转储所有相关数据并重命名它的方法。请提供有关替代方法的建议 - 利弊。

【问题讨论】:

  • 您的 ID 列是否有 newsequentialid() 的默认约束?如果没有,您应该使用顺序值重建聚集索引,这可能是您获得低性能的原因
  • 我同意 newsequentialid() 会提供更好的性能。感谢您的建议。
  • 是一次性操作,还是时不时执行?

标签: sql-server performance sql-delete


【解决方案1】:

由于你确实想删除的百分比很高,所以你可以考虑这种方法

 SELECT col1, col2, ... INTO #SomeHoldingtable
            FROM MyTable WHERE ..condition..

 TRUNCATE TABLE MyTable

 INSERT MyTable (col1, col2, ...)
           SELECT col1, col2, ... FROM #SomeHoldingtable

【讨论】:

    【解决方案2】:

    如果我理解正确,过滤索引和批量删除应该会有所帮助(SQL Server 2008 或更高版本):

    create index IX_1 on dbo.Table1 (Column1, Column2, ...) include (Table2ID) where Column1 is NULL and Column2 is NULL and ...
    
    create table #Deleted (Table2ID uniqueidentifier NULL)
    create index #IX_Deleted on #Deleted (Table2ID) where Table2ID is not NULL
    
    
    select 1
    while @@rowcount > 0
        delete top (50000) T
        output deleted.Table2ID into #Deleted (Table2ID)
        from dbo.Table1 T
        where Column1 is NULL and Column2 is NULL and ...
    
    select 1
    while @@rowcount > 0
        delete top (50000) T
        from dbo.Table2 T
            join (select distinct Table2ID from #Deleted where Table2ID is not NULL) D on D.Table2ID = T.ID
    
    drop table #Deleted
    drop index IX_1 on dbo.Table1
    

    并且,根据需要(一次操作,或定期),可以保留索引IX_1

    在 SQL Server 2005 上,可以对索引计算列进行同样的操作。

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多