web-dev-qa-db-ja.com

Rails:カスケード削除と依存破壊

2つのテーブルがあると仮定します:usersorders。ユーザーには多くの注文があるため、当然、私の注文テーブルには外部キーuser_idがあります。

Rails(速度、スタイル、参照整合性の観点から))で、ユーザーが削除された場合、すべての依存する注文も削除されるようにするためのベストプラクティスは何ですか?次のオプションを検討しています:

ケース1.ユーザーモデルで:dependent => :destroyを使用する

ケース2. postgresと書き込みでテーブルの順序を定義する

user_id integer REFERENCES users(id) ON DELETE CASCADE

ケース1を使用する理由はありますか?ケース2は私がやりたいことをすべてやっているようです。実行速度に違いはありますか?

29
apotry

それは本当にあなたが望む行動に依存します。ケース1では、関連付けられた各注文でdestroyが呼び出され、そのため ActiveRecordコールバック も呼び出されます。ケース2では、これらのコールバックはトリガーされませんが、はるかに高速になり、参照整合性が保証されます。

アプリケーションの初期段階では、:dependent => :destroyそれは、データベースに依存しない方法で開発できるようにするためです。スケーリングを開始したら、パフォーマンス/整合性の理由からデータベースで実行する必要があります。

29
Peter Brown

has_many :orders, dependent: :destroy

  • データの整合性を自動的に維持するための最も安全なオプション。
  • 多態的な関連付けがあり、トリガーを使用したくない。


add_foreign_key :orders, :users, on_delete: :cascade(データベース移行中)

  • 多態的な関連付けを使用していないか、多態的な関連付けごとにトリガーを使用したい。


has_many :orders, dependent: :delete_all

  • Has_manyが関連ツリーのリーフノードである場合にのみ使用します(つまり、子には外部キー参照との別のhas_many関連がありません)。
19
WiredIn

私はオプション1を使用します。それは機能するかもしれませんが、オプション2でいくつかの問題を確認できます。

  1. ActiveRecordはこれらのレコードが削除されたことを認識しないため、動作が不安定になる可能性があります
  2. ユーザーを削除するとすべての注文も削除されることを意味するので、コードを読んでいる人にはわかりません。
  3. orderのdestroyハンドラは起動しません

確かにオプション2の方が速いと思いますが、トレードオフの価値があるかどうかはあなた次第です。アプリケーションのユーザーの削除は一般的な操作ですか?

別のオプションは、:dependent => :delete_allを使用することです。これは:dependent => :destroyよりも高速で、上記の1と2の欠点を回避します。詳細は こちら を参照してください。

6
f1sherman