4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【DB】スキーマレスからの脱却:なぜ「ちゃんと設計されたスキーマ」が必要になるのか

Posted at

はじめに

この記事では、スキーマレスなデータベースを使ってきたプロジェクトが、なぜスキーマを持つデータベースへの移行を検討するようになるのかを解説します。

この記事の対象読者

  • MongoDBやDynamoDBなどのNoSQLデータベースを使っている方
  • データ分析やBI活用で困りごとを感じ始めている方
  • スキーマ設計の重要性を理解したい方

想定するシチュエーション

開発初期にスキーマレスなデータベースを採用し、柔軟にデータを保存してきたものの、運用が進むにつれて「データの形がバラバラで集計しづらい」「分析クエリが複雑になりすぎる」といった課題に直面しているケースを想定しています。

スキーマとは何か

スキーマとは、データベースに保存するデータの構造を定義したものです。テーブルにどんなカラムがあり、それぞれがどんな型で、どんな制約を持つのかを事前に決めておくことで、データの一貫性を保ちます。

スキーマあり(RDBなど)の特徴

RDB(リレーショナルデータベース)のようなスキーマを持つデータベースでは、テーブル構造を事前に定義します。

定義例(テーブル設計)

CREATE TABLE users (
  id         INT          NOT NULL PRIMARY KEY,
  name       VARCHAR(100) NOT NULL,
  email      VARCHAR(255) NOT NULL UNIQUE,
  created_at TIMESTAMP    NOT NULL
);

この例では、カラム名・型・必須/任意・制約(NOT NULL、UNIQUEなど)があらかじめ決まっています。定義に合わないデータは挿入できません。

メリット

  • データの形が揃う
  • JOINや集計がやりやすい
  • 型の保証があるため、安全に扱いやすい
  • 長期運用しやすい

デメリット

  • スキーマ変更にマイグレーションが必要
  • 開発初期の仕様変更に対応しづらい
  • テーブル設計に時間がかかる

スキーマレス(DocumentDB/MongoDBなど)の特徴

スキーマレスなデータベースでは、ドキュメント(レコード)ごとに異なる構造を持つことができます。

データ例(JSON)

// あるドキュメント
{
  "id": 1,
  "name": "Taro",
  "email": "taro@example.com"
}

// 別のドキュメント
{
  "id": 2,
  "fullName": "Jiro Yamada",
  "mail": "jiro@example.com",
  "tags": ["beta-user"]
}

この例では、namefullNameemailmail のように、フィールド名がバラバラでも保存できてしまいます。また、後から tags のような新しいフィールドを自由に追加できます。

メリット

  • 開発初期に仕様がコロコロ変わるときに超ラク
  • アプリ側のオブジェクトをほぼそのまま保存できる
  • スキーマ変更が不要で柔軟性が高い

デメリット

  • データの形がどんどんバラける
  • 後で分析するときに「結局どのフィールドを見ればいいの?」問題になる
  • 型が揃っていない、nullだらけ、フィールド名が微妙に違うなどの地獄が起きる

スキーマレスとスキーマありの使い分け

それぞれの特性を理解した上で、適材適所で使い分けることが重要です。

開発初期やプロトタイプではスキーマレスの柔軟性が活きますが、運用が進み組織的なデータ活用が求められるようになると、スキーマありのデータベースが必要になってきます。

なぜ「スキーマレスから脱却したい」と感じるのか

開発初期はスキーマレスが便利

プロジェクトの初期段階では、要件が頻繁に変わるため、スキーマレスなデータベースは非常に便利です。

  • ユーザーフィードバックに応じて素早く機能追加できる
  • テーブル設計を気にせず、まずは動くものを作れる
  • アプリケーション側の変更がそのままデータ構造に反映される

この柔軟性は開発速度を大きく向上させます。

運用が進むと見えてくる課題

しかし、時間が経つにつれて以下のような問題が顕在化してきます。

データの形がバラバラになる問題

// 初期のユーザーデータ
{
  "id": 1,
  "name": "Taro"
}

// 途中で追加された項目
{
  "id": 2,
  "name": "Jiro",
  "email": "jiro@example.com"
}

// さらに後から別の形式で
{
  "id": 3,
  "fullName": "Hanako Suzuki",
  "mail": "hanako@example.com",
  "registeredAt": "2024-01-01"
}

同じ「ユーザー」を表すデータなのに、フィールド名や含まれる情報が異なってしまい、後から処理するのが大変になります。

分析・集計の難しさ

分析クエリを書くたびに以下のような処理が必要になります。

  • 「このフィールドがあるドキュメントだけを抽出して...」
  • 「型が違うデータを変換して...」
  • 「複数のフィールド名のどれかが存在するか確認して...」

BIツールから綺麗に可視化することも難しくなり、結果的に分析のハードルが上がってしまいます。

チーム運用の課題

組織的な課題も出てきます。

  • 新メンバーが来たときに、データ構造がカオスで理解コストが高い
  • 「この数値を公式指標にしたい」と思ったときに、定義が安定しない
  • データの品質を保証できず、信頼性が低下する

これらの課題から「ちゃんとスキーマを切って、テーブル設計して、分析用のきれいな世界を作ろう」という考えに至るわけです。

脱却する際の典型的なアプローチ

二層構造の考え方

スキーマレスから完全に離れるのではなく、用途に応じて使い分ける二層構造がよく採用されます。

アプリ層:スキーマレスDBで柔軟性を保つ

アプリケーションのトランザクション処理やリアルタイムな読み書きには、引き続きスキーマレスDBを使います。

  • ユーザーのアクション記録
  • セッション情報
  • リアルタイムなデータ更新

これらは仕様変更の可能性が高く、柔軟性が求められるためです。

分析層:DWHでスキーマを定義して整理する

一方、分析用途には以下のようなDWH(データウェアハウス)を使い、スキーマをしっかり定義します。

  • Amazon Redshift
  • Google BigQuery
  • Snowflake
  • Azure Synapse Analytics

ETL処理(Extract, Transform, Load)を通じて、スキーマレスDBから定期的にデータを抽出・変換・ロードすることで、分析に適した形に整えます。

具体的な移行パターン

典型的な移行の流れを見てみましょう。

ステップ1:現状分析

まず、スキーマレスDBに保存されているデータの構造を把握します。

  • どんなフィールドが存在するか
  • データ型はどうなっているか
  • null値の割合はどれくらいか

ステップ2:スキーマ設計

分析に必要なテーブル構造を設計します。

-- ユーザーテーブルの例
CREATE TABLE users (
  user_id       BIGINT       NOT NULL PRIMARY KEY,
  user_name     VARCHAR(100) NOT NULL,
  email         VARCHAR(255) NOT NULL,
  registered_at TIMESTAMP    NOT NULL
);

-- イベントログテーブルの例
CREATE TABLE event_logs (
  event_id      BIGINT       NOT NULL PRIMARY KEY,
  user_id       BIGINT       NOT NULL,
  event_type    VARCHAR(50)  NOT NULL,
  event_data    JSON,
  occurred_at   TIMESTAMP    NOT NULL,
  FOREIGN KEY (user_id) REFERENCES users(user_id)
);

ステップ3:ETLパイプライン構築

データ変換のロジックを実装します。例えば、Apache AirflowやAWS Glueなどを使って、定期的にデータを同期します。

# 疑似コード例
def transform_user_data(raw_document):
    return {
        'user_id': raw_document.get('id'),
        'user_name': raw_document.get('name') or raw_document.get('fullName'),
        'email': raw_document.get('email') or raw_document.get('mail'),
        'registered_at': raw_document.get('created_at') or raw_document.get('registeredAt')
    }

ステップ4:段階的移行

いきなり全てを移行するのではなく、重要度の高いテーブルから段階的に進めることで、リスクを抑えます。

ステップ5:検証・改善

実際に分析クエリを実行してみて、パフォーマンスやデータ品質を検証し、必要に応じて改善します。

まとめ

スキーマレスとスキーマありは、それぞれ異なる強みを持っています。

スキーマレスが適している場面

  • 開発初期で仕様が流動的
  • アプリケーションのトランザクション処理
  • リアルタイム性が求められる用途

スキーマありが適している場面

  • 組織的なデータ活用・分析
  • 長期運用が必要なシステム
  • データの一貫性と品質が重要

多くの場合、両者を組み合わせた二層構造が現実的な解決策となります。アプリケーション層ではスキーマレスの柔軟性を活かしつつ、分析層ではスキーマを定義してデータの品質を保つことで、それぞれの強みを最大限に引き出すことができますね。

もしあなたが「分析クエリが複雑になってきた」「データの形がバラバラで困っている」と感じているなら、それはスキーマを持つDWHの導入を検討する良いタイミングかもしれません。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?