jfluteの日記スマートフォン用の表示で見るjfluteの日記2012-11-16論理削除がデータを汚しているDBDesignベクトルの違うデータまあ、それは事実。履歴をそのまま残したいということも事実。いちいち削除履歴テーブルなんて作ってられないのも事実。※ここでの論理削除は、復活する論理削除じゃなく、物理削除の代わりとして履歴のための論理削除を指します。(復活する論理削除って、そもそも削除とは言えないって気も...)本来、論理削除されたデータって...そのテーブルの定義するデータとはベクトルの違うデータである考えます。削除されたデータを保持するテーブルを作ると、それはそれで面倒なのでそのまま同じテーブルに持ったままにする。その方が扱いが簡単なことが多いから。個人的には、業務上重要なテーブルに関しては、しっかりと「削除履歴テーブル」を用意して、本体のテーブルには常に有効なデータだけがある状態の方が、データメンテもプログラムも遥かに楽になりますし、なんといってもデータが安全です。テーブルを限定すればそんなに数も多くならないし。ユニーク制約とのトレードオフポイントは、ユニーク制約が貼れるかどうかFOOとBARカラムで業務上ユニークなテーブルがあるとして、でも、そのテーブルに削除フラグ(DEL_FLG)があったら、少なくともFOOとBARの複合ユニークは貼れません。(削除も含めて、FOOとBARはユニークって仕様ならいいですが、まあ、あんまりそういうことはないかなぁと)FOOとBARと「削除フラグ=false」でユニークになります。FOOとBARと「DEL_FLG=true」ではユニークにならない。削除フラグをユニーク制約に含めることはできない。DEL_FLG=true」のデータが大量にあるかもしれないから。ユニーク制約がないと何が困るかって、一言でずばり「なんでも入っちゃう」ってところ。DEL_FLG=false」も、複数入ってしまう可能性があるってこと。CORGEってカラム多かったり、例えば、FOOの値によってユニーク性が若干変わったり、そのテーブルに登録するアプリ(アクター)が複数あったり。とあるすれ違いで入ってしまう可能性はなきにしもあらずです。したときに重複データが入ってしまって、「一件検索が二件になってエラーになっちゃった」とか。ないけど、でも確かにそういうトラブルは世の中発生しています。スピード重視の今の時代、その辺の厳密なチェック実装に時間をなかなかかけてられない、っていうならなおさら。逆に言うと、少ない労力の仕組みで最低限の担保ができればうれしい。仕様考えてテストすれば(お金かければ)OKでしょ、っていう考えが通じる現場は徐々に少なくなってきています。テストも大事ですが、一方で仕組みによる防御を加えることも大事。エラーで困るってだけでなく、そのあとのデータメンテも大変で、同じ落ちるにしても、せめてデータがブロックされていれば。そのブロックを検知して排他制御的な処理がされてれば。(というかそれが理想かな)本来、ユニーク制約を貼るってのはとても簡単なこと。ERDツールでちょっとカラム選択して制約作っておけば済む話。実はそれだけで、運用後のメリットが享受できてるわけですね。削除履歴テーブルなんてもの作ってられないというなら、そこはやっぱりトレードオフ、そのリスクは背負わないといけない。リスクは背負いたくない。「削除フラグがfalseのときだけFOOとBARがユニーク」っていうユニーク制約が貼れたらいいのになぁって、何人もの人から聞いた言葉ですが、まあDBMSにはないです。いって、トリガーでぐちゃぐちゃ頑張りたくない。回避的なやり方をよく見かけます。入れて、削除されたデータには削除した日時をそのまんま入れる。「FOOとBARと削除日時」でユニーク制約。アプリが有効なデータを登録するときにマジック日付をしっかり固定で登録してくれさえすれば成立します。回避的ってなんか後ろ向きな感じですが、そして「うへぇ」って叫んじゃいそうなやり方ですが、でも、やらないよりはマシかもなぁとは思います。登録や更新が色々なプロセスから実行されて、構造が複雑なテーブルなら、しのご言ってられないって。その削除フラグ、どういう...?自分もまだ思考中のテーマです。そもそも論理削除に関しては、取り扱いが難しいと思っています。検索する側は、どういうときにその削除フラグを見るの?って、見直して欲しい場面が多々あります。(全テーブル削除フラグとかって、ほんと憂鬱に...)jflute流で言えば、削除フラグにはDBコメントが絶対に必須です。無言で存在している削除フラグほど、プログラマーを惑わせるものはないと考えています。ユニーク制約の大切さそして...ユニーク制約をどう貼るか!?DB設計の中ではマニアックな要素だと思いますが、これが運用後のメンテナンスで発揮するんですねー。貼ってしまえばあまりに当たり前のことなので、「ユニーク制約様のおかげです」って声に出して言わないので、やっぱりまあ地味なことには変わりはないんでしょうけど。ユニーク制約違反を、EntityAlreadyExistsExceptionというクラスでcatchできるようにしています。画面ごとに細かく制御しないにしても、統一的に「そのデータ既にあるよんメッセージ」を出す画面に遷移さえしていればって感じで。注文は削除されません......ちなみにこちらの考え方、とても共感しています。InfoQ一度生まれたものが、状態が変わっただけと言えるので「意味のわかりやすい状態」で管理をしたいなと。実際にそういう風にDB設計することが多いですね。その後、論理削除の記事を見つけた(2015/3/24)DB設計するときは、面倒がらずにしっかり考えて、空間をデザインしていきたいものですね。Releasedあけましておめでとうございます。ER図を書く機能を評価してます。再開したディズニーシーにはてなブログをはじめよう!jfluteさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。