web-dev-qa-db-ja.com

テーブルのデータの90%を効率的に削除する

テストに必要なのは10%だけなので、テーブルのデータの90%を削除するプロセスに取り組んでいます。

私が見つけた最良の方法は、テーブルの行の10%を一時テーブルに格納することです。

現在の方法

SELECT TOP 10 PERCENT *
INTO #temp_some_table
FROM some_table (nolock)
ORDER BY some_column DESC

TRUNCATE TABLE some_table 

INSERT INTO some_table 
SELECT *
FROM #temp_some_table 

DROP TABLE #temp_some_table 

この方法ではtempdbがいっぱいになり、ディスクもいっぱいになります。

ご質問

テーブルのデータの90%を削除するより効率的な方法はありますか(DELETE TOP 90 PERCENT FROM sometable

または

バッチを使用して、some_tableのデータの10%を一時テーブルに挿入する方法はありますか?このようなもの:

DECLARE @r INT;

WHILE @r > 0
BEGIN

BEGIN TRANSACTION;

INSERT INTO [dbo].[##temp_cds_Basket]
SELECT TOP 10 PERCENT *
FROM [dbo].[cds_basket] s

SET @r = @@ROWCOUNT;
print @r 

COMMIT TRANSACTION

END

可能な解決策

これはどう?

SET NOCOUNT ON;

DECLARE @r INT;
DECLARE @TenPercentDate datetime 
with cte (some_column) as (

    select top 10 percent some_column from some_table (nolock) order by some_column desc
)
select @TenPercentDate = min(some_column)
from cte

select @TenPercentDate

 SET @r = 1;

WHILE @r > 0
BEGIN
  BEGIN TRANSACTION;

 DELETE TOP (10000) from
  some_table 
  WHERE some_column < @TenPercentDate  

  SET @r = @@ROWCOUNT;
  print @r

  COMMIT TRANSACTION;

  --CHECKPOINT;    -- if simple

END

--rollback
5
Craig Efrein

上記のコメントで述べた3つの異なるアイデアがあります。ここでは、少なくとも1つの詳細について説明します(自己診断されたトンネルビジョンのために立ち往生しています)。

  1. まあ、10%を構成する行の数を事前に計算し、それをバッチで比較することができます。

私はこれについて考えていましたが、実際に比較する必要はありません。保持したいデータのエッジにある日時の値を把握し、古い行がなくなるまでチャンクを削除できます。例えば:

SET NOCOUNT ON;

DECLARE 
  @rc INT = 1, 
  @cutoff DATETIME, 
  @batchsize INT = 10000;

;WITH x(dt) AS 
(
 SELECT TOP (10) PERCENT datetime_column
  FROM dbo.mytable 
  ORDER BY datetime_column DESC
)
SELECT TOP (1) @cutoff = dt -- earliest row we want to keep
 FROM x
 ORDER BY dt;

WHILE @rc > 0
BEGIN
  DELETE TOP (@batchsize) dbo.mytable
    WHERE datetime_column < @cutoff
  SET @rc = @@ROWCOUNT;
END

これを強化するいくつかの追加の方法については この投稿 を参照してください。

  1. 切り捨て/挿入の代わりにドロップ/選択先を検討し、この操作中に一括ログ復旧を使用することも検討できます。

これは有効なオプションであり、上記よりも痛みが少ないはずです。

  1. 1つのデータ移動操作を実行することもできます。
SELECT TOP 10 PERCENT cols
  INTO dbo.newtable
  FROM dbo.oldtable
  ORDER BY datetime_column;

DROP TABLE dbo.oldtable;

EXEC sys.sp_rename N'dbo.newtable', N'dbo.oldtable', N'OBJECT';

これもそれほど苦痛ではありませんが、ドロップを実行する前に必要なデータを確実に取得できるように、デバッグを自由に注入してください。

後者の両方のケースでは、テーブルを単に削除することを妨げる制約、スキーマにバインドされたビューなどが存在する可能性があることに注意してください(当然、切り捨てることができるため、インバウンドの外部キーは問題ではありませんが、アウトバウンドにはまだ必要な場合があります対処する)。既存のプランにも影響があり(データの90%を削除すると、統計がプランを更新して無効化するため、違いはありません)、@ Kennethが以下で指摘するように、アクセス許可を再確立する必要があります新しいテーブル(事前にそれらをスクリプト化できることを確認したい場合があるため)。

10
Aaron Bertrand