2011-11-22 2 views
0

Please recommend the best bulk-delete optionに質問を提起したので、CASCADE制約は、一括レコードが読み込まれたときにすべてのテーブルのレコードを削除できないようにするものです。なぜCASCADE制約により、バルクレコードを持つテーブルの操作が妨げられていますか?

DELETE FROM table1のときにCASCADEに時間がかかる理由はありますか。またはTRUNCATE table1 CASCADEを実行しようとしていますか?

参考までに、私はPostgreSQL 8.1.4を使用しています。時代遅れですが、私のテーブル(トップリンクに記載されています)でCASCADE制約を削除すると、DELETEとTRUNCATEの両方のクエリが正常に動作します。

しかし、CASCADEは私の必要なものです!私はただの制約を取り除くことはできません。これで私を助けてください。

+0

テーブルに大量のレコードが読み込まれたときに、制約を削除することさえできませんでした。 postgresqlのバージョンはどれほど奇妙ですか? – Siva

+0

私はあなたが何を求めているのか分かりません。もちろん、CASCADEd制約のために関連するすべての行を削除する必要がある場合は、DELETEに時間がかかります。そして、あなたは**本当に**、**本当に**アップグレードするべきです。少なくとも最新の8.1バージョン(8.1.23) –

答えて

1

よくある間違いは、外部キーの列にインデックスがないことです。参照先テーブルから1つの行を削除するときは、すべての参照行を検索する必要があります。インデックスごとにSLOWシーケンシャルスキャンが実行されます。インデックスを使用すると、簡単で高速です。

これはおそらく問題です。

+0

PostgreSQLでは、外部キーターゲットには一意のインデックスが必要です。外部キーターゲットを持たない場所は指定できません。それは問題ではありません。 PostgreSQLの単一シーケンシャルスキャンと何千ものインデックススキャンとの間のトレードオフについて上記の私の指摘を参照してください.... –

+0

それは間違っているためdownvotedです。 –

+0

@ChrisTravers、私は確かに "外来キーの列にインデックスがない"とは、参照する列を意味します。外部キー=ローカル側、ユニークキー=リモート側。 – sayap

0

カスケード削除の使用は非常に貧弱です。あなたはなぜそれを発見しましたか?大量のレコードが削除されると、時間がかかりすぎます。子レコードから始めて正しく削除する必要があります。多数のレコードを削除する場合は、ロックを避けるために、バッチで削除するスクリプトを作成し、1つのコマンドに長時間を要することがあります。

なぜそれが遅くなるのか説明しましょう。 TableAという親テーブルから1000レコードを削除するとします。 3つの子テーブルが含まれています。表Bは、親レコードごとに平均10レコードです。 TableCは、親レコードあたり平均5レコードです。 TableDは、一行のレコードにつき100レコードを平均します。したがって、表Aの1000件のレコードを削除するには、実際に115000件のレコードを削除する必要があります。ここで、tableAから10,000レコードを削除しているとしたら、カスケード削除によって1,150,000レコードが削除されるようになりました。ほとんどのデータベースでは、親テーブルは3つ以上の関連テーブルを持つことができます(100を超えるFKSを持つテーブルがあります)。データベース上でカスケード削除を許可し、誰かが1,000レコードを削除しようとすると、数億のレコードが削除されてしまいます。

+1

これらのレコードは、とにかく削除する必要があります。だから、なぜ子レコードからの削除が速いのか説明していない。私は先に進み、その部分に答えました。 –

+0

多くのテーブルをロックする1つのトランザクションですべてを行う必要はないので、バッチ処理が可能です。 – HLGEM

0

小規模な操作ではCASCADE DELETEが有効ですが、大きな操作ではパフォーマンスが低下します。裏で何が起こっているのかを見なければならない理由を理解するには、PostgreSQLではトリガを使用します。

親テーブルから削除すると、削除するすべての行について、子テーブルに移動して削除されます。これは削除された行ごとに発生します。さて、PostgreSQLではシーケンシャルスキャンが比較的安価であるため、単一のシーケンシャルスキャンが非常に高速になると、多数のインデックススキャンが強制される可能性があります。

テーブル1で1000個のレコードを削除するとします。つまり、テーブル2では10000個のレコードが削除されています。これを正しく実行すれば、テーブル2から削除して、のスキャンを1回実行してを実行します。良いハードウェアで数秒かかるかもしれません。その後親レコードから削除して、これは高速です。いいですよね?

は、今、私たちは、私たちが削除1000行ごとに、表1から.....

スキャンして削除を行うテーブル2のインデックスをスキャンし、10行を削除、次に行くためのトリガーに依存していると仮定します。私たちは、OSのプリフェッチルーチンから得ることができるすべての助けを完全に失います。ずっと少数のシーケンシャルリードのために、冗長なランダムページ読み込みをたくさん置き換えます。今、私たちは、ディスク・プラッタが回転して動くのを待つのに多くの時間を費やしています。ああ......

ON DELETE CASCADEトリガーがその役割を果たします。私たちがいくつかのレコードから削除するだけであれば問題ありません。しかし、それらは一括削除で非常に速く離れます。トランザクション内ですべての削除をラップし、最初に子テーブルから削除すると、はるかに高速になります。

関連する問題