Upgrade to Pro — share decks privately, control downloads, hide ads and more …

テーブル設計のよくある罠と それに対する処方箋

kensho
June 01, 2024
51

テーブル設計のよくある罠と それに対する処方箋

【DMM×バイセル】若手エンジニアによる学生向けTech Study Summit
https://dmm-recruit.connpass.com/event/316914/
登壇資料

kensho

June 01, 2024
Tweet

Transcript

  1. 2 自己紹介 名前 岩下 拳勝 各種SNSアカウント x: @iwashi623 GitHub: @iwashi623

    入社時期 2023年7月 所属・職域 店舗買取アプリケーション Storeチーム・BE/インフラ担当 趣味 プロ野球観戦・散歩・旅行
  2. 3 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  3. 4 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  4. 9 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  5. 10 サンプルアプリケーション紹介 よくある記事投稿アプリケーションを作るシチュエーションを想定して、ケーススタディ的に発表を進め ます。 アプリケーションの最初の要件は以下です。 要件 • ユーザーが登録できること • 記事を投稿できること

    ◦ 記事は下書き(Draft)、公開済み(Published)、非公開(Unpublished)に状態変化できること ◦ 記事一覧画面などで使用する、サムネイル画像を添付できること • あらかじめ用意された記事種別を選択できること ◦ 記事種別・・・記事の内容ではなく形式(ニュース?ブログ?論文?ポエム?etc..)を選択する • あらかじめ用意された記事カテゴリを選択できること ◦ 記事カテゴリ・・・記事の中身でどういった内容(スポーツ?芸術?事件?etc…)を選択する
  6. 11 サンプルアプリケーション紹介 パッと思いつくテーブル設計 • users(著者) ◦ ユーザー(記事作成者)を保 存する • post_categories(記事カテゴリ)

    • post_types(記事種別) • posts(記事) ◦ posts.statusは記事のステー タスを保存 ◦ posts.image_urlで画像を保 存する
  7. 12 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  8. 13 罠1. 乱用されるフラグ 追加される要件 • 記事を削除できるようにしたい。 ◦ ただし、一度公開済みで削除された記事に関しても、いつかデータとしては使うかもし れない。 ▪

    つまりDB上から物理削除はしたくない。 • ユーザー、記事種別、記事カテゴリについても、削除ができるようにしたい。 ◦ ユーザー、記事種別、記事カテゴリが削除されている場合は、それに紐づく記事は非 公開としたい。 ▪ もちろんこちらも物理削除はしたくない。
  9. 14 罠1. 乱用されるフラグ 追加される要件 • 記事を削除できるようにしたい。 ◦ ただし、一度公開済みで削除された記事に関しても、いつかデータとしては使うかもし れない。 ▪

    つまりDB上から物理削除はしたくない。 • ユーザー、記事種別、記事カテゴリについても、削除ができるようにしたい。 ◦ ユーザー、記事種別、記事カテゴリが削除されている場合は、それに紐づく記事 は非 公開としたい。 ▪ もちろんこちらも物理削除はしたくない。 本当によくある
  10. 38 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  11. 43 罠2. 悲しい非正規化 この設計の問題点 • 画像が3枚以上増えることが考慮されていない。 • image_urlが削除されたとき、image2_urlやimage3_urlなどが登録されていてもサムネイルとして表示され ない。 •

    「image2_urlが空なのに、image3_urlにはデータが登録されている」のようなことが起こり得る ◦ 画像を表示するときも、 if post.image_url != nil などの処理を書くことになって辛い。 • 単純に画像を送信するフォームを作るのと、フォームから送られたきた情報をカラムにマッピングする処理を 書くのがめんどくさすぎる。 ◦ めんどくさいということはバグを生みやすいということ。
  12. 47 罠2. 悲しい非正規化 処方箋② ”サムネイル画像”というデータを”画像”というデータとは別の場所に持つ ここでは、posts.thumbnail_urlというカラ ムを追加して対応している。 “画像データ”と”サムネイルデータ”という データの責務分割をする。 →

    サムネイルが登録されていないとい う事態を防ぎやすくなった。 注)サムネイルは通常1記事につき1枚という認識の上、カラ ム追加で対応していますが、サムネイル複数登録したかっ たらテーブル追加での対応にしてもいいかもです。
  13. 48 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  14. 51 罠3. 消えた履歴 数日後・・・ CS(カスタマーサポート)の人 「3月に記事を作成して料金もお支払いしたユーザーの方から、『今 月は新規の記事公開をしていないのに料金の請求書が来た!どういうことだ!』といったお問い 合わせがありました。ご確認いただけますか?」 ぼく「はい、確認します」 〜〜〜調査〜〜〜

    ぼく「あ、あれ、どうなってるんだ …。 あ、posts.published_atが5月になっている…。まさか、3月に公開後に、一度非公開になってから 再公開された? どうしよう、3月に公開された時点のデータが無くなっちゃった …」
  15. 53 罠3. 消えた履歴 現在の設計の問題点 • ステータスの更新履歴のデータを保持していなかったこと。 • 公開済みの記事を取得するクエリに、 WHERE posts.status

    = ‘Published’という条件を毎回 つける必要があること。 ◦ つけ忘れて非公開の記事が公開されてしまったら大問題になる。
  16. 55 罠3. 消えた履歴 処方箋① 記事の更新履歴テーブルを作成する statusに更新がかかるたびに、 post_status_logsにデータをINSERTし ていく。 → こうすることで、古い公開データが

    消えることなくステータスを更新でき る。 サービス使用料の請求は、最初にス テータスが公開になった日時のデータ を使って行えば良い。
  17. 57 アジェンダ 1. 自己紹介 2. 導入 3. サンプルアプリ紹介 4. 罠1.

    乱用されるフラグ 5. 罠2. 悲しい非正規化 6. 罠3. 消えた履歴 7. まとめ 8. 参考文献
  18. 60 参考文献 • @n_yamadamadamada(かのかの) (2023)『会員状態を例に状態管理 のデータベース設計を考える 』 • 曽根 壮大

    (2015)『PostgreSQLアンチパターン』 • 曽根 壮大 (2019)『失敗から学ぶRDBの正しい歩き方』 • 和田 卓人(2015)『SQLアンチパターン 幻の第26章「とりあえず削除フラ グ」』