システム設計Tweet引き続き「SQLアンチパターン」について、自分なりのチェックポイントを言語化していきたいと思います。下記の記事の続きです。www.ketancho.net本題に入る前に、ふたつ。嬉しかったこととお詫び(?)を。素晴らしいエントリをありがとうございます。『SQLアンチパターン』は名著であると胸を張って言えます。ご興味をお持ちの方はこの機会にぜひ。拙い部分があると思いますが、自分の理解のために拙くてもいいので言語化を続けていこうと思っています。引き続きよろしくお願いします。読んでいただけました。コメントもたくさん頂けたのですが、そのなかで「常にグッドパターンがいいとは限らない」というコメントがありました。いうか、本の中にも「アンチパターンを用いてもいい場合」という記載があるんです。私がそれを省いてしまっているんです。少なくともこの本が「常にグッドパターンがいい」と言っている本ではないということだけご理解ください。自分の言葉でまとめている意図としては、DB設計する際のインデックスとして役立てたい似た状況があれば、記事を参考にした上で、該当する本の章に立ち返りたい最終的にはこの本の知識を、本を参照せずとも息を吸うように考えられるようになりたい(=エンジニアとしての血肉にしたい)だったりします。インデックスなので、本の内容をサマライズして、かつ、自分の理解に置き換えてしまっています。気になる章があった方は、ぜひ本を読んでみてください。間違いなく学びにつながると思います。log4ketanchoそれでは、本題の内容です。前回は論理設計でしたが、今回は物理設計の話です。型を定義してしまうのはアンチパターンです。型で下記のように定義したとします。13.29この場合、月末に働いた時間にhourly_rateを掛けたときに、計算結果が微妙にズレてしまいます。微妙なズレであれば許容される場合はFLOATで構いませんが、そうでない場合はFLOATの利用は避けるべきです。正確な値を求めたい場合は、NUMERICやDECIMALといった精度を設定できるデータ型を利用します。上の例であれば、NUMERIC(4,2)という型で定義することで、丸め誤差が発生しなくなります。ある都立高校で生徒情報を管理するときに、住んでいる区を列に保存するとします。いずれかの区に住んでいました。この表現には嘘があります。以外は挿入したくないため、テーブル定義時に、下記のような制約を定義したとします。場合は、下記のようにも定義できます。'KITA'));しかし、このように列定義で列に入る値を縛る方法は下記のような問題を発生させるため、アンチパターンと言えます。取りうる値を調べるのが難しい新入生のデータを追加する画面を作成するときに、区(ward)として選択できる項目をドロップダウンで表示したいところです。その列に取りうる値をメタ情報として管理してしまっており、候補値のリストを簡単に取得することができません。フロントサイドかバックエンドサイドで何らかの方法でリスト管理する必要があり、テーブル定義を変更したら、もう一方も変更しなくてはならず、リスト二重管理になってしまっているといえます。バグの要因となる可能性があります。新しい値を追加するのも難しい(削除も)私の入学する年から学区が撤廃されました。そのため、葛飾(KASTUSHIKA)といった値が入りうることになりました。(私の地元は葛飾です!!)このような追加作業は、(データベースエンジンの種類によりますが、)一筋縄にはいかないことが多いです。最悪の場合、一度テーブルの値を空にする必要があるエンジンもあり、毎年の制度変更の都度、テーブル移行という心臓がドキドキする作業をする必要がでてきます。(私はやりたくありません。別に参照テーブルを用意するのが正解と言えます。KITAWardward(PK)BUNKYOTOSHIMAITABASHIKITAこの設計であれば、取りうる値を取得することも容易ですし、新しい値を追加するのも簡単です。ファントムファイル(幻のファイル):「何が何でもファイルはDBの外側で保持しなくちゃ!」と考えていないか※このパターンについては、アンチパターンとグッドパターンという明確な分け方はありません。言うのであれば、「何が何でもファイルをDBの外側で」と思考停止してしまうことがアンチパターンと言えます。利用者のプロフィール写真といった、静的データをシステムで保持する要件があったとします。物理ディスクやS3といった外部ストレージにファイルの実体を保存し、DBにはそのファイルの保管先のみを保存する、というのがよくある設計パターンです。このように外部で管理する場合、DBの容量を減らせる容量が減らせるので(静的ファイル以外の)バックアップ時間を短く抑えられる静的ファイルへの参照が用意になる(クエリを投げなくてもプレビューできる)といった利点があります。システムからファイルを削除する際に、DBへのクエリを投げるとともに、静的ファイルを削除する必要があるその場合、トランザクション管理することができないので、ロールバックもできないDBのバックアップとは別に、静的ファイルのバックアップ方式を検討する必要がある静的ファイルへのアクセス権限はDBとは別に考える必要があるといったデメリットもあります。型としてDBに保存する設計とした場合、このような問題(手間)は発生しません。これらふたつの設計はメリデメがある、ということになります。どちらが適しているかは要件次第といえます。厳密なトランザクション管理が必要であればDB側に保存する、といったように設計時に検討してください。この章のアンチパターンは「絶対にDB以外の場所に静的ファイルを置かなくてはならない」と決めつけること、とのことです。「常にふたつの設計を検討候補に加えること」を心がけたいと思います。個人的に、まさにこのアンチパターン的考えに陥っていました。(外部に置くポリシーのプロダクトにしか関わったことがなく、かつ私自身そういうものだと思考停止していたと思います。インデックスショットガン(闇雲インデックス):インデックスは正しく定義されているか、あるいは、インデックスを活かした検索をしているかアンチパターン例なんでもかんでも(本来不要な)インデックスを定義している「インデックスを定義すれば検索が速くなるんですよね?!」と無邪気に定義したにも関わらず、有効活用されないケースです。有効活用するならいいんです。再構成するコストが増えてしまい、パフォーマンスを悪化させてしまいます。際に余計なコストがかかるんでしょ?」と心配して、インデックスを毛嫌いするパターンです。本の中にもありますが、データベースのクエリの大半は参照系です(参照系であることが多いです。