2017-09-16 14 views
0

を行を削除し、私はSQL Server 2012の標準データベース(復旧モデルが「シンプル」である)で、次のPipelineArchivesのテーブルを持っている:表がBody列でアーカイブされたデータを保持しているSQL Serverの - 効率的

enter image description here

。これは時間が経つにつれて成長し、現在11,914行と合計53GBのデータを含んでいます。現在の日付より3ヶ月前にCreatedOnの値を持つすべての行を削除するクエリを実行したいと思います。

私は

DELETE FROM PipelineArchives 
WHERE CreatedOn < MyDate 

ときMyDate基準の結果、いくつかの行で実行しようとしたクエリは、数秒でSSMSから[OK]を実行します。しかし、日付を増やすと229行に30秒かかりました。

ローを削除する方が効率的ですか?

+0

申し訳ありません - EAVは何ですか? –

+1

行を現在の日付から3か月間別の表にコピーします。元のテーブルを削除して、名前を変更してください.... –

+2

[EAV =エンティティ属性値](https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model) –

答えて

2

削除を増やすと、テーブルのロックが防止され、他のトランザクションが実行されます。より多くのCPUとメモリを使用しますが、より熟練しています。

DECLARE @archiveId BIGINT 

WHILE (SELECT COUNT(*) FROM PipelineArchives WHERE CreatedOn < MyDate) > 0 
BEGIN 

    SELECT TOP 1 @archiveId = PipelineArchiveId 
    FROM PipelineArchives 
    WHERE CreatedOn < MyDate 

    DELETE PipelineArchives 
    WHERE PipelineArchiveId = @archiveId 

END 
+1

条件の行が存在するかどうかをチェックする(「WHERE EXISTS(SELECT ...)」)かどうかをチェックするよりも、毎回エントリを数えるほうが効率が悪いです。また、最初にIDを選択するのではなく、 'DELETE TOP(1)...'を実行してください。 –

+0

TTあなたは正しいです、本当に毎回生産テーブルを数えたくありません。しかし、論理は熟練した方法です。ループを変更し、@counter変数を使用することができます。 – mvisser

0

時には正しいことはその逆を行うことです。

新しいテーブルPipelineArchivesNewを作成し、PipelilneArchiveswhere CreatedOn >= MyDateの行をコピーします。必要なデータがすべて新しいテーブルに入ったら、PipelineArchivesPipelineArchivesOldに、PipelineArchivesNewPipelineArchivesにそれぞれ変更します。次に、PipelineArchivesOldをドロップします。

これは、システムの設定方法に応じて、適切なソリューションである場合とそうでない場合があります。

+0

非常に悪い考えです。これがあなたのプロダクションテーブルの場合。あなたのインデックス、トリガー、またはテーブルのセキュリティ権限はどうですか?これは何もコピーされません。もう一度セットアップする必要があります。 – mvisser

0

また、あなたは変数なしで試すことができます。

SET ROWCOUNT 5 

WHILE (SELECT COUNT(*) FROM PipelineArchives WHERE CreatedOn < MyDate) > 0 
BEGIN 
    DELETE PipelineArchives 
    FROM PipelineArchives 
    WHERE CreatedOn < MyDate 
END 

SET ROWCOUNT 0