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

レガシーで硬直したテーブル設計から変更容易で柔軟なテーブル設計にする

Avatar for Red Frasco Red Frasco
November 20, 2025

 レガシーで硬直したテーブル設計から変更容易で柔軟なテーブル設計にする

2025/11/15に開催されたJJUG CCC 2025 Fall( https://jjug.doorkeeper.jp/events/190868 )の登壇資料です。

Avatar for Red Frasco

Red Frasco

November 20, 2025
Tweet

More Decks by Red Frasco

Other Decks in Technology

Transcript

  1. 自己紹介 佐々木 興平(ささきこうへい ) - 株式会社 Red Frasco(2025/08〜) - シニアソフトウェアエンジニア

    ◆ 経歴 株式会社Red Frasco (exエキサイト,exセレス,exCA,exぐるなび,exQUICK) ◆ その他コメント - キャリアはバックエンド畑を中心 - 組織マネジメント・プロセス改善も随時実施 - 教科書通りにやるのが苦手 2
  2. データベースの歴史 12 RDB以前 ~1970年 階層型データベース ネットワーク型 データベース リレーショナルデータベース RDB 1970年〜

    NoSQL 2000年〜 関係モデル(集合論と述 語論理)に基づいてSQLで データ操作が可能、ACID 特性を担保 GraphDB Key-Value NewSQL 2010年〜 大量リクエストの処 理が可能、ACID特性 はほとんどない (MongoDBは例外) 基本的なRDBの仕様 をある程度保持しつ つ、大量リクエスト処 理が可能、ACID特性 を担保
  3. データベースの歴史 13 RDB以前 ~1970年 階層型データベース ネットワーク型 データベース リレーショナルデータベース RDB 1970年〜

    NoSQL 2000年〜 関係モデル(集合論と述 語論理)に基づいてSQLで データ操作が可能、ACID 特性を担保 GraphDB Key-Value NewSQL 2010年〜 大量リクエストの処 理が可能、ACID特性 はほとんどない (MongoDBは例外) 基本的なRDBの仕様 をある程度保持しつ つ、大量リクエスト処 理が可能、ACID特性 を担保
  4. データベースの歴史 14 RDB以前 ~1970年 階層型データベース ネットワーク型 データベース リレーショナルデータベース RDB 1970年〜

    NoSQL 2000年〜 関係モデル(集合論と述 語論理)に基づいてSQLで データ操作が可能、ACID 特性を担保 GraphDB Key-Value NewSQL 2010年〜 大量リクエストの処 理が可能、ACID特性 はほとんどない (MongoDBは例外) 基本的なRDBの仕様 をある程度保持しつ つ、大量リクエスト処 理が可能、ACID特性 を担保 データベースは進化している
  5. レガシーなテーブル設計のイメージ 17 設計上の問題 - 更新回数のカラムだけど特定の数字(例: 99)だけ特別な意味 - インデックスの欠乏もしくは過剰 - カラム数が多すぎる神テーブル

    - データ量が増えてくるとパフォーマンスが急落する 保守性の低さ - 不要なカラムがそのまま残っている(削除できない) - 予備カラム(space_1,space_2, memo_1,memo_2 etc..)
  6. (スピーカーが思う )レガシーなテーブル設計のイメージ 18 性能上の問題 - カーディナリティの低いカラムにインデックスが張られている - (効果が薄い)外部キーの濫用 - insert、update、deleteが遅い

    - 過剰な正規化によるパフォーマンスの劣化 - 論理削除の濫用によるデータ量増加でのパフォーマンス劣化 設計上の問題 - updated_atが何を更新した時刻か分からない - フラグカラムの乱立 - 動的カラム名(campaign_2024, campaign_2025) - データ項目の追加時に影響範囲が読めない = 調査工数が増える
  7. レガシーなテーブル設計はなぜ発生するのか? 20 そもそも.... - データが増えなければ、初期設計は良い設計 になっている(はず) - 項目が増えなければ、初期設計は良い設計 になっている(はず) -

    項目追加 = カラム追加の思考 になっている - カラム追加の方が工数が節約できる (と思っている) - テーブルを追加するのは謎の承認フローが必要(だったりする?) - フレームワークが勝手に テーブル設計をしてくれるから関心がない - テーブル設計の方法は特に教えてもらっていない - GoogleやAIに聞いても、あんまり明確な答えが返ってこない
  8. テーブル設計の方法とは? 22 アプリケーションコードは設計方法が豊富 - MVC - Clean Architecture - MVVM

    - ドメイン駆動開発(DDD) - Vertical Slice Architecture - Onion Architecture - Layered Architecture - Functional Programming - Object Oriented Programming
  9. テーブル設計の方法とは? 23 アプリケーションコードは設 計方法が豊富 - MVC - Clean Architecture -

    MVVM - ドメイン駆動開発(DDD) - Vertical Slice Architecture - Onion Architecture - Layered Architecture - Functional Programming - Object Oriented Programming 種類も豊富で情報もたくさん 進化している感じがする!
  10. テーブル設計の方法とは? 24 テーブル設計は? - 要件の洗い出し - 概念設計 - 物理設計 -

    論理設計 - 整理 - 正規化 - テーブル定義書 - SQLアンチパターン?
  11. テーブル設計の方法とは? 25 - テーブル設計は? - 要件の洗い出し - 概念設計 - 物理設計

    - 論理設計 - 整理 - 正規化 - テーブル定義書 - SQLアンチパターン? どの説明も抽象度が高すぎて、具体が イメージできない。さらに、時間軸ベー スの説明や対処法がないので、データ が肥大化すると詰む。 進化している感じがしない。
  12. テーブルが格納するデータの特性や重要性 29 データとコードの経過年数と物量 - データ: 経過年数 * 利用頻度で積み上がっていく - コード:

    経過年数でコードは増加するが、初期に書かれたコードは減少する サービスが成長するとコードも増加するが、データ も肥大化する。しかし、データは過去のものを開発 者の都合で容易には変更できない。そして変更し ないほうがよい。
  13. 変更容易で柔軟なテーブル設計にするには? 今までのスライドの課題を折り込んだものにする - 世の中に落ちてるテーブル設計論に寄りかからない - 過去に対する変更を行わない - 未来への変更を折り込む - データ量の増加

    - 格納する項目の追加 - 利用しなくなった項目の削除 - 利用しなくなったデータの削除 - サービス仕様変更によるデータの扱われ方の変更 - 一般的ではないテーブル設計方法を採用する覚悟(大事) 33
  14. 変更容易で柔軟なテーブル設計にするには? 過去に対する変更を行わない ALTER文やUPDATE文を極力使用しない。 - ALTER文を実行するデメリット - カラム追加により、過去の設計に改変を加えている - 過去のデータのデフォルト値どうするんだっけ?など余計なことを考える -

    ALTER文の実行中にロックがかかったりする(Online DDLでもある) - アプリケーションのロールバック時に手順が発生する - UPDATE文を実行するデメリット - いつ更新されたかわからない。(updated_atを更新し忘れ問題) - updated_atが変更されても何を更新したのかわからない - 通常のビジネスロジックを通ってきてない可能性もある 35
  15. 変更容易で柔軟なテーブル設計にするには? 過去に対する変更を行わない - ALTER文 -> CREATE TABLE文 + INNER JOIN文で対応

    - 既存テーブルのデータの過去改変が発生しない - 新テーブルに必要なデータだけが入り, null大量のカラムとかできない - UPDATE文 -> DELETE & INSERT文で対応 - 最新のデータのみを保持するテーブルにする - 一度にINSERTできるくらいのテーブルに分割する - updated_atなどは不要 - 変更履歴が必要な場合は、${テーブル名}_logテーブルを作成し格納 36
  16. 変更容易で柔軟なテーブル設計にするには? 過去に対する変更を行わない よくある質問 - ALTER文 -> CREATE TABLE文 + INNER

    JOIN文で対応 - Q. JOINが多くて性能劣化になりそう - A. なってからいいましょう - A. 1対1のデータなら気にすることない - A. 必ず一緒になるデータは集約作業を行いJOIN数を削減する(後述) - A. OUTER JOIN も使用は可 37
  17. 変更容易で柔軟なテーブル設計にするには? 過去に対する変更を行わない - 集約作業について - 複数のテーブルを1テーブルにする作業のこと - 手順(右のER図を使用して) - news_contentテーブルを作成

    - news_tilte, news_article, news_contentに更新処理をダブルライト - 参照をnews_contentに変更 - news_title, news_articleの更新を停止 - news_title, news_articleのテーブル名をリネーム - news_title, news_articleを削除 - 約2〜4週間かけて段階的に行うのがオススメ - サービス無停止で集約作業は可能。日中にやっても問題ない。 38
  18. 変更容易で柔軟なテーブル設計にするには? 過去に対する変更を行わない - UPDATE文 -> DELETE & INSERT文で対応 - Q.

    常に最新のデータしかみられなくなる - A. ${テーブル名}_logテーブルを使用して過去データを参照可能 - Q. 全部created_atにしていいのか? - A. 問題なし。変更がされないことが担保されていた方がいい - Q. 外部キーが使えないのでは? - A. 使えません。更新処理が局所化されるので、バリデーション等が毎回すべて通る思想 で使用する。どうしても外部キーを使用する場合は、UPSERTなどを使用すること。 39
  19. 変更容易で柔軟なテーブル設計にするには? 未来に対する変更を折り込む - テーブル追加時に実行計画とセットでレビューする - 使用しなくなったテーブルはすぐに削除を行う - 手順 - 参照が外れているかを確認(SQLファイルでテーブル名をGrepで可能)

    - テーブルをリネームする - テーブルをドロップする - データ量の増加に対応する - パーティションで対応(アプリケーションの変更が不要) - シャーディングで対応(アプリケーションの変更が必要) - New SQLで対応(アプリケーションの変更が必要 & 金の力で叩く) 40
  20. 変更容易で柔軟なテーブル設計にするには? 未来に対する変更を折り込む - サービス仕様変更によるデータの扱われ方の変更 - 例) フラグや状態をサービス仕様の都合で変更したい - フラグ専用テーブル(原則1フラグ1テーブル)を用意する -

    状態テーブル(場合により1状態1テーブル, 多状態1テーブル)を切り替える - コードで状態管理が正常化どうかを検証する(EnumやSealedを使用することが多い) 41 ユーザーの状態は別テーブルで管理する 重複しないようにビジネスロジックをDbUnit等で 徹底的にテストする
  21. 導入に際して実際にあった Q&A - Q. テーブル数が増えてしまう - A. 問題ない。MySQLもPostgreSQLも1スキーマ40億テーブル設置可能. - A.

    ネーミングルールを厳密にしないと探すのが大変になる - Q. パフォーマンスは出るのか? - A. 1つ1つのテーブルのインデックスサイズは小さくなり、メモリに載りやすくなる ので、パフォーマンスは向上する ことが多い - A. 追加、削除、更新も局所的に実装可能なのでインデックスの更新のパフォー マンスは向上 することが期待できる - Q. 管理が大変にならないか? - A. 数は多くなるので大変にはなる。DTOやMapper自動生成(MyBatis Generator やJOOQなど)で緩和可能。 44