データベースとDBMSの理解
これまで個人開発をする中で、PostgreSQLやMySQL、SQLiteなど、いくつかの「データベース」を使ってきました。使い方を調べながら実装していましたが、データベースとは何かについて深く考えたことはあまりありませんでした。
そんな中、仮想通貨データを分析する際にDuckDBというソフトウェアを知りました。 DuckDBでは、Parquetファイルに保存されたデータを、データベース内のテーブルへ取り込まずに直接問い合わせることができます。
ここでふと、「データベースなのにデータを内部に保持せずParquetファイルを直接扱えるとはどういうことか」という疑問が浮かびました。 そして、恥ずかしながら、これまでデータベースとDatabase Management Systemをあまりきちんと区別せず使っていたことに気が付きました。
そこで本記事では、データベース、DBMS、SQLなど、データベース周辺の基本的な用語とその関係を整理します。
そもそもデータベースとは何か
「データベースとは何か?」と聞かれたとき、データを保存する場所と考えると、なんとなくイメージはできます。 しかし、データを保存するだけなら、CSVやParquetなどのファイルでもできます。
例えば、仮想通貨のデータ分析では、
- 価格データ
- 注文データ
- 約定データ
など、さまざまなデータを扱います。 これらをそれぞれファイルを作成し、無秩序に保存しておいては分析時に必要なファイルをいちいち探す必要があります。そこで、各データをデータベースとして以下のように整理・保存します。
Database
│
├─ prices
│ └─ 価格データ
│
├─ orders
│ └─ 注文データ
│
└─ trades
└─ 約定データ
このように整理しておくことで、
- 価格データだけを取り出す
- 特定の注文に対応する約定を確認する
- 複数種類のデータを組み合わせて分析する
といった処理がしやすくなります。 つまり、データベースは単なる「保存場所」というより、複数のデータを一定のルールに従って整理し、後から検索・利用しやすい形にしたものと考えると分かりやすいです。
そして、このように一定の構造に従って保存したデータベースを管理するソフトウェアがDatabase Management System(以下、DBMS)です。
データベースとDBMSは何が違うのか
DBMSは、日本語では「データベース管理システム」と呼ばれます。 データベースとDBMSの関係を単純化すると、次のように考えられます。
DBMS
│
│ 作成・管理・操作
↓
Database
│
├─ prices
├─ orders
└─ trades
Databaseは、一定の構造に従って整理されたデータの集合です。 一方のDBMSは、そのデータベースを作成・管理・操作するためのソフトウェアです。
普段なんとなく「データベース」と呼んでいる、
- PostgreSQL
- MySQL
- SQLite
- DuckDB
などは、厳密にはDBMSです。
例えばPostgreSQLを使ってデータベースを作成するとき、PostgreSQLというDBMSを使ってcrypto_dataというデータベースを作り、その中のテーブルにデータを格納する、といった関係になります。
DBMSは何をしてくれるのか
DBMSは、データを管理・操作するためのさまざまな機能を提供します。
データを検索する
大量のデータから条件に一致するデータを検索できます。 例えば、BTCの価格データだけ欲しい といった要求に対して、条件を指定してデータを取得できます。
データを追加する
新しく発生したデータを追加できます。 例えば、新しい価格データや注文データを既存のデータへ追加できます。
データを更新する
すでに保存されているデータを変更できます。 例えば、銘柄に関する情報が変更された場合に、該当するデータを更新できます。
データを削除する
不要になったデータを条件に従って削除できます。
データ構造を管理する
「どのようなデータを、どのような構造で管理するか」を定義できます。
例えば、
prices
timestamp
symbol
price
という構造を定義して、価格データを管理できます。
データの整合性を保つ
DBMSには、不正なデータや矛盾したデータが登録されることを防ぐための仕組みがあります。 例えば、「必ず値が入っていなければならない」や「同じIDを重複して登録してはいけない」といった制約を設定できます。
複数のデータを関連付けて扱う
データを複数のテーブルに分け、それらの関係を利用してデータを扱うこともできます。 例えば、価格データと銘柄情報を別々に管理し、必要なときに組み合わせて取得するといったことができます。
さらにDBMSによっては、データを安全かつ効率的に扱うために、
- トランザクション:複数の処理をひとまとまりとして安全に実行する
- 同時アクセス制御:複数の利用者や処理が同時にデータへアクセスする状況を制御する
- 権限管理:誰がどのデータを操作できるか管理する
- インデックス:特定のデータを効率よく検索できるようにする
といった機能も提供します。
製品によって提供される機能や得意分野には違いがありますが、重要なのは、
DBMSは単なるデータの保存場所ではなく、データを安全かつ効率的に管理・操作するための機能を提供するソフトウェア
だということです。
CSV・Parquetへの保存とは何が違うのか
では、CSVやParquetにデータを保存する場合と、DBMSを利用する場合では何が違うのでしょうか。
例えば、
prices.csv
や、
prices.parquet
としてデータを保存するとします。 これらはファイルなので、Pythonから利用する場合は、概念的には次のような流れになります。
Python
↓
CSV / Parquetファイルを読み込む
↓
Python側でデータを処理する
CSVやParquetは、データをどのような形式でファイルに保存するかを定めたものです。 一方、DBMSを利用する場合は、役割が少し変わります。
Python
↓
DBMSへ問い合わせる
↓
DBMSがデータを検索・操作する
↓
必要な結果をPythonへ返す
例えば、100万件の価格データがあり、その中からBTCのデータだけが必要だとします。 DBMSを利用する場合、アプリケーションは「BTCのデータを取得したい」という条件をDBMSへ伝えます。DBMS側が条件に合うデータを検索し、その結果をアプリケーションへ返すことができます。 つまり、DBMSがデータを管理・操作する役割の一部を担ってくれるわけです。
特に、以下のような状況では、DBMSが提供するデータ管理機能が役に立ちます。
- データを頻繁に追加・更新する
- 複数種類のデータを関連付ける
- データの整合性を管理したい
- 複数の利用者やアプリケーションからアクセスする
一方で、常にDBMSを使うほうが良いわけではなく、 何をしたいのかによって、ファイル保存とDBMSを使い分けることが重要です。
SQLとは何か
データベースについて調べると、必ずと言っていいほど登場するのがSQLです。 SQLは、 Structured Query Language の略で、ざっくりと言うとDBMSに指示を出すための言語です。 主にリレーショナルデータベースで使われ、データ構造の定義やデータの検索・追加・更新・削除などを行うことができます。
例えば、pricesテーブルからBTCのデータを取得したい場合、次のようなSQLを書けます。
SELECT *
FROM prices
WHERE symbol = 'BTC';
このSQLは、
pricesテーブルから、symbolがBTCであるデータを取得する
という指示です。 SQLでは代表的に、
| 命令 | 用途 |
|---|---|
| SELECT | データを取得する |
| INSERT | データを追加する |
| UPDATE | データを更新する |
| DELETE | データを削除する |
といった操作ができます。
例えばPythonからPostgreSQLを利用する場合、概念的には、
Python
↓
SQLで指示
↓
PostgreSQL(DBMS)
↓ 管理・操作
Database
├─ Table
├─ Table
└─ ...
という関係になります。
RDB・RDBMSとは何か
ここまで説明してきたデータベースは、主にリレーショナルデータベースを想定しています。 リレーショナルデータベースでは、データをテーブルとして表現し、テーブル同士の関係を利用しながらデータを扱います。
そして、リレーショナルデータベースを管理するDBMSを、**Relational Database Management System(RDBMS)**と呼びます。 例えば、
- PostgreSQL
- MySQL
- SQLite
- DuckDB
はいずれも、リレーショナルなデータモデルとSQLを扱うDBMSです。 ただし、すべてのデータベースがリレーショナルデータベースというわけではありません。
例えばMongoDBやRedisなど、リレーショナルデータベースとは異なるデータモデルを扱うDBMSもあります。 これらは一般にNoSQLという文脈で紹介されることがあります。
Database・DBMS・SQLの関係を整理する
ここまで登場した用語を整理してみます。
アプリケーション(Pythonなど)
│
│ SQLで指示
↓
DBMS(PostgreSQL / MySQL / SQLite / DuckDBなど)
│
│ 管理・操作
↓
Database
├─ Table
├─ Table
└─ ...
それぞれの役割は、
Database:一定の構造に従って整理されたデータの集合。
DBMS:Databaseを作成・管理・操作するためのソフトウェア。
SQL:主にリレーショナルデータベースのデータや構造を定義・操作・問い合わせするための言語。
という関係になります。
DuckDBとParquetの関係
本記事は、DuckDBではParquetファイルに保存されたデータを、データベース内のテーブルに取り込まず直接問い合わせることができるという点に疑問を感じたことがきっかけで整理しました。
DuckDBは、DBMSですが、自身のデータベースだけでなく、Parquetなどの外部ファイルを直接問い合わせることもできます。 つまり、DuckDBが持つDBMSとしての機能を、外部ファイルに対して行使することができます。
DuckDBをデータベースではなく、DBMSとして理解することで、当初の疑問を解消することができました。
まとめ
これまでPostgreSQLやSQLiteを何となく「データベース」と呼んでいましたが、データベースとDBMSを正しく理解することで、開発する際のシステムの役割分担についても理解しやすくなりました。正しく勉強せずなんとなくの理解で使用している技術が多いので、今後も気づいたら調べて整理していきたいと思います。