web-dev-qa-db-ja.com

パフォーマンスを改善するためのソフト削除:すべて間違っていますか?

数年前にソフト削除を読んだところ、削除のパフォーマンスが向上しました。実際にアイテムを削除してクラスター化された(およびその他すべての)インデックスに影響を与えるのではなく、値を変更するだけだからです。

私は最近これを試しました、そして、私は非常に残念なパフォーマンスを得ました。

そこで、ソフト削除の適切な実装についてWebを検索しましたが、最初に読んだのは「ソフト削除は悪い」という記事やブログでした。

テーブルが巨大になると、それは良いよりも最も害を及ぼすようです...

毎晩(毎日)のメンテナンスにより、削除対象としてマークされたすべての行が(実際には)削除されるため、私が行ったことがテーブルをもっと巨大なテーブルにするとは思いません。

では、ソフト削除は本当にパフォーマンスに悪いのでしょうか?実際に削除すると、クラスター化されたテーブル全体が完全に並べ替えられますか(これは多くのディスク操作になります!!!)?

場合によっては、一時的な削除が永続的なものではありません。削除をバックグラウンドジョブに任せるだけで(たとえば、インデックスを再編成/再構築する直前に)、元のトランザクションは削除が発生するのを待つ必要がなくなります(特に、カスケード削除、トリガーなどがある場合)。

他のケースでは、ソフト削除はパフォーマンス要件ではなく、データの完全な削除を回避する方法であるため、常にその痕跡があります。その場合は、一時的削除を永続的にする必要があります。 (しかし、ある時点で大量のデータを「削除」すると、テーブルはほとんど「削除」されたデータになります。それがパターンであり、データを永続的に保持することが要件である場合は、アーカイブテーブルを使用して削除されたデータを保持することを検討できます。行は、遅延バックグラウンドタスクとして実行することもできますが、元のトランザクションがフラグを更新するだけで十分です。)

どちらの場合も、 フィルターされたインデックス を使用してランタイムパフォーマンスを向上させることができます。どの列を含める必要があるかをガイドすることはできませんが、次のように言うことができます。

CREATE INDEX x ON dbo.table(col) INCLUDE(othercol)
WHERE deleted = 0;

直感に反するように聞こえるかもしれませんが、少なくとも削除する行を識別するという点で、削除操作を高速化するために逆インデックスも必要になる場合があります。その場合、おそらくそこに主キーが必要なだけです。

CREATE INDEX y ON dbo.table(key) WHERE deleted = 1;

多くの制限があることに注意してください:

6
Aaron Bertrand