1.はじめに
データベースのテーブル設計について調べていると、「RDBでは正規化する」「NoSQLでは取得したいデータをまとめて保持する」といった説明をよく目にします。
しかし、最初にそれを知ったときは、
「なぜデータベースの種類が違うだけで、ここまで設計方法が変わるのだろう?」
という疑問がありました。
調べてみると、その違いはデータベースの性能や仕組みだけでなく、どのような考え方でデータを管理するのかという設計思想の違いによるものでした。
今回は、RDBの代表例としてCloud SQL、NoSQLの代表例としてApache Cassandraを取り上げ、
- RDBとNoSQLの設計思想の違い
- テーブル設計の考え方
- 利用シーンに応じたテーブル分割のポイント
について、書店システムを例に解説します。
2.今回登場するデータベース
今回比較対象として扱うのは、次の2つのデータベースです。
①Cloud SQL
Google Cloudが提供するフルマネージドのリレーショナルデータベース(RDB)です。
MySQL、PostgreSQL、SQL Serverなどをクラウド上で運用でき、バックアップやアップデートなどの運用をGoogleが担ってくれます。
本記事では、RDBの例としてCloud SQLを取り上げます。
②Apache Cassandra
Apache Cassandraは、Apache Software Foundationが提供するオープンソースの分散型NoSQLデータベースです。
もともとはFacebookで開発され、その後Apacheプロジェクトへ寄贈されました。
大量データを複数サーバーへ分散して保持でき、高い可用性とスケーラビリティを持つことが特徴です。
本記事では、NoSQLの例としてCassandraを取り上げます。
今回はこの2つを比較しながら、
- RDBではなぜ正規化を行うのか
- NoSQLではなぜデータをまとめて保持することが多いのか
について解説していきます。
3.RDBとNoSQLの違い
まずは、それぞれの特徴を整理します。
| 項目 | RDB(Cloud SQLなど) | NoSQL(Cassandraなど) |
|---|---|---|
| データ整合性 | ◎ | △ |
| JOIN | 可能 | 基本不可 |
| トランザクション | 可能 | 苦手 |
| 大量データ | △ | ◎ |
| スケール | △ | ◎ |
RDBはデータの整合性を重視しています。
一方、Cassandraは高速な読み書きとスケーラビリティを重視しています。
つまり、
- RDBは「データを正しく管理する」
- Cassandraは「高速に大量のデータを取得する」
という設計思想の違いがあります。
この違いが、そのままテーブル設計の考え方にも現れます。
RDBではデータの整合性を保つために正規化を行い、NoSQLでは大量にある必要なデータを高速に取得するため、取得方法を意識したテーブル設計を行います。
それでは、実際の例を見ながら違いを見ていきましょう。
4.書店システムを例に考える
今回は書店システムを例に考えてみます。
例えば、
「書店にはどのような本があるのか知りたい」
という要件があったとします。
取得したい情報は次の4つです。
- 書籍名
- 著者名
- ISBN
- 価格
この要件をCloud SQLとCassandraで設計すると、考え方が大きく変わります。
①Cloud SQLでは正規化する
RDBでは、データの重複を減らすために正規化を行います。
例えば、書店システムでは次のようにテーブルを分割します。
books
| book_id(主キー) | title | isbn | price | author_id(外部キー) |
|---|---|---|---|---|
| 1 | 吾輩は猫である | 978-4-09-386001-3 | 800 | 1 |
| 2 | こころ | 978-4-10-101013-7 | 400 | 1 |
authors
| author_id (主キー) | author_name |
|---|---|
| 1 | 夏目漱石 |
著者名を毎回保存するのではなく、author_idだけ保持します。
書籍情報を取得したい場合は、SQLで外部キーを使い、booksテーブルとauthorsテーブルをJOIN(結合して取得します。
結合結果
| book_id | title | isbn | price | author_id | author_name |
|---|---|---|---|---|---|
| 1 | 吾輩は猫である | 978-4-09-386001-3 | 800 | 1 | 夏目漱石 |
販売情報を管理したい場合も、新たにsalesテーブルを作成し、book_idなどの外部キーで管理します。
(customer_nameなどの顧客情報も重複しうるので、customerテーブルとして別に定義すべきですが今回は説明のために割愛させてください)
sales
| sales_id(主キー) | book_id(外部キー) | sale_date | customer_name | quantity |
|---|---|---|---|---|
| 1 | 1 | 2024-01-01 | 山田花子 | 2 |
このようにすることで、
- データの重複が減る
- 更新漏れを防げる
- データの整合性を保ちやすい
というメリットがあります。
②Cassandraではクエリや取得したい情報を中心に考える
CassandraではJOINができません。
そのため、
「どのようなデータを取得したいか」
を最初に考えてテーブルを設計します。
例えば書籍情報を取得したいのであれば、
books
| isbn(主キー) | title | author_name | price |
|---|---|---|---|
| 978-4-09-386001-3 | 吾輩は猫である | 夏目漱石 | 800 |
| 978-4-10-101013-7 | こころ | 夏目漱石 | 400 |
のように、一つのテーブルへまとめて保持します。
つまり、
1回のクエリで必要な情報を取得できること
を優先して設計します。
販売情報も一緒に取得するケースが多いのであれば、
- 販売情報を内包する
- 用途ごとに別テーブルを用意する
など、取得方法を基準に設計します。
books
Cassandraでは、上記のようにテーブルの中に配列(テーブル)のデータを入れることが出来ます。
この考え方はQuery First Design(クエリ主導設計)とも呼ばれています。
5.Cloud SQLとCassandraを比較すると
同じ「書籍情報を取得したい」という要件でも、設計方法は大きく異なります。
Cloud SQLでは、必要なデータをJOIN(結合)して情報を取得します。
一方CassandraではJOINができないため、最初から必要な情報を保持します。
つまり、
- Cloud SQLは「重複を減らす設計」
- Cassandraは「取得しやすい設計」
を目指していると言えます。
6.テーブル設計時の注意点
①RDBは正規化しすぎても良くない
RDBでは正規化が重要ですが、何でも分割すれば良いわけではありません。
例えば、
- ISBN
- タイトル
- 価格
まで全て別テーブルへ分割してしまうと、
books
| book_id (主キー) | isbn_id (外部キー) | title_id (外部キー) | price_id (外部キー) | author_id (外部キー) |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 |
isbn
| isbn_id(主キー) | isbn |
|---|---|
| 1 | 978-4-09-386001-3 |
title
| title_id(主キー) | title |
|---|---|
| 1 | 吾輩は猫である |
price
| price_id(主キー) | price |
|---|---|
| 1 | 800 |
author
| author_id (主キー) | author_name |
|---|---|
| 1 | 夏目漱石 |
というように、取得するたびに5つのテーブルのJOINが必要になります。
その結果、
- SQLが複雑になる
- 保守しづらくなる
- パフォーマンスが悪化する
可能性があります。
つまり、
利用シーンを考え、適切な粒度で分割すること
が重要です。
②NoSQL(Cassandra)でも全部まとめれば良いわけではない
逆にCassandraでも、
「全部まとめておけば良い」
という話ではありません。
例えば販売履歴を大量に保持するとします。
books
この場合、booksテーブルの1レコードの容量が非常に大きくなり、パフォーマンスが低下する可能性があります。
また、
販売履歴だけ分析したい場合でも、毎回毎回booksテーブル内のsalesの情報まで読み込む必要があります。
そのため、
- 販売情報だけ更新することが多い
- 販売分析を頻繁に行う
- 1冊あたりの販売履歴が非常に多い
といったケースでは、下記のように販売情報を別テーブルに分けた方が適している場合もあります。
つまり、NoSQL(Cassandra)でも用途に応じたテーブル設計が重要になります。
7.テーブル設計で意識したいこと
RDNでもNoSQLでも、
最も重要なのは
「利用シーンを考えて設計すること」
です。
例えば、
- 更新頻度は高いか
- 一緒に取得することが多いか
- データ量はどれくらいか
- 将来どのような検索や分析を行う予定か
こうした点を考慮して、
「分割するか」
「まとめるか」
を判断する必要があります。
データベースの種類だけで設計を決めるのではなく、実際の利用方法に合わせて設計することが大切です。
8.まとめ
RDBでは、
- 正規化を基本とする
- データの重複を避ける
- JOINを利用して必要な情報を取得する
NoSQLでは、
- クエリを中心に設計する
- JOINは行わない
- 必要な情報を1回で取得できるよう設計する
ことが基本になります。
ただし、
- RDBだから何でも正規化する
- NoSQLだから何でも内包する
というわけではありません。
将来の利用シーンやメンテナンス性、パフォーマンスまで考慮した上で、適切な粒度でテーブルを設計することが重要です。
この記事が、RDBとNoSQLのテーブル設計の違いを理解するきっかけになれば幸いです。
最後まで読んでいただき、ありがとうございました!
9.参考資料
RDB(リレーショナルデータベース)とは|NoSQLとの違いやメリットを紹介
わからないなりに理解したいデータベース⑥:NoSQL編:Cassandra
分かりやすく正規化について理解しよう (データベース)


