本文へスキップ
totonoe.tech

プログラミング言語を整える

初級

データベースを整える。

= PostgreSQL・MySQL・DuckDB・MongoDB・Redis を並べて、同じお題の書き方の違いを見比べる

データベースが初めての方は、先に そもそもデータベースとは・どんな場面で使うか をどうぞ。

そもそもデータベースとは

データを整理して置き、必要なときにすぐ取り出せるようにした、大きな棚。

データベースは、データを決まった形で整理して保存し、探す・追加する・直す・消すを、速く安全にできるようにした仕組みです。Excel のファイルと違い、大量のデータを、たくさんの人が同時に使っても壊れにくいように作られています。Web サービスの会員情報や注文の記録は、ほとんどがデータベースに入っています。

種類は大きく分けて、表の形で整理して SQL で扱うリレーショナルデータベース(RDB)と、SQL を使わないNoSQLがあります。PostgreSQL・MySQL・SQLite は RDB、MongoDB は文書の形で持つ NoSQL、Redis はキーと値をメモリで扱う NoSQL です。DuckDB は分析に向いた組み込み型の RDB です。どれが優れているかではなく、目的に合うものを選びます。

どこで・どんな場面で使うか

  • Web サービスの保存先

    会員・商品・注文・投稿など、サービスの記録の置き場になります。

  • 業務システム

    販売管理・在庫・会計・勤怠など、会社の記録を扱うシステムの土台です。

  • データ分析

    溜めたデータを集計して、売上や利用状況を調べる場面で使われます。

  • 高速な読み書き・キャッシュ

    メモリ上で動くデータベースを、表示の高速化や一時的な保存に使います。

  • 求人での位置づけ

    開発・運用の職種では「データベースの経験」が広く求められます。どの製品かも、募集ごとによく書かれています。

なぜ覚えておくと得か

  • システムの全体像が読める。画面・サーバー・データベースという三つの役割がわかると、障害や仕様の話についていきやすくなります。
  • 選び方の基準が持てる。「この用途ならどのタイプか」を考えられるので、技術選定の会話に加われます。
  • SQL が土台になる。RDB の多くは SQL を使うので、一つ覚えれば他にも通用します。

下の表で、五つのデータベースの種類・誕生・ライセンスを見比べられます。気になったものは、それぞれのページの練習場で触ってみてください。

5つのデータベース

各ページでは、概要・同じ6つのお題・出力当てクイズ・よくあるエラーをまとめています。練習場の「本物」はブラウザの中で本物の処理系が動くもの、「再現」は動きを JavaScript で再現したものです。

データベース 種類 誕生 ライセンス 練習場
PostgreSQL リレーショナルデータベース(RDB) 1986年にカリフォルニア大学バークレー校で始まった研究プロジェクト POSTGRES が元で、SQL に対応した Postgres95 を経て、1996年に PostgreSQL と名前を改めました PostgreSQL License(BSD や MIT に近い寛容なライセンス) 本物が動く(PGlite)
MySQL リレーショナルデータベース(RDB) 1995年 GPL v2 と商用ライセンスのデュアルライセンス なし(解説のみ)
DuckDB 組み込み型の分析用(列指向)データベース 2019年 MIT License 本物が動く(DuckDB-WASM)
MongoDB ドキュメント指向データベース(NoSQL) 2009年(10gen 社が開発を始め、同社は2013年に社名を MongoDB 社に改めました) SSPL(Server Side Public License)。2018年から。それ以前は AGPL(GNU Affero General Public License)でした。SSPL は OSI が認めたオープンソースライセンスではありません 再現(mingo)
Redis インメモリのキーバリューストア 2009年 7.2 までは BSD ライセンス。2024年の 7.4 から RSALv2 と SSPLv1 のデュアルライセンスに変わり、2025年の Redis 8 で AGPLv3 も選べるようになりました 再現(表示は本物と照合)
SQLite 組み込み型のリレーショナルデータベース 2000年 パブリックドメイン 本物が動く(sql.js)

並べ替えて2ページ目を取る

5つのページの同じお題のコードです。どれも、各ページの「準備」のデータを入れた後に流したものです。

PostgreSQLリレーショナルデータベース

SELECT id, name, price
FROM products
ORDER BY price DESC
LIMIT 2 OFFSET 2;

MySQLリレーショナルデータベース

SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 2 OFFSET 2;

DuckDB組み込み型の分析用

SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 2 OFFSET 2;

MongoDBドキュメント指向データベース

db.products.find({}, { name: 1, price: 1 }).sort({ price: -1 }).skip(2).limit(2)

Redisインメモリのキーバリューストア

ZREVRANGE products:by_price 2 3 WITHSCORES

あれば更新・無ければ追加

5つのページの同じお題のコードです。どれも、各ページの「準備」のデータを入れた後に流したものです。

PostgreSQLリレーショナルデータベース

INSERT INTO products (id, name, category, price) VALUES
  (2, 'みかん', '果物', 90),
  (6, 'バナナ', '果物', 100)
ON CONFLICT (id) DO UPDATE
  SET price = EXCLUDED.price;
SELECT * FROM products ORDER BY id;

MySQLリレーショナルデータベース

INSERT INTO products (id, name, category, price) VALUES
  (2, 'みかん', '果物', 90),
  (6, 'バナナ', '果物', 100)
AS new
ON DUPLICATE KEY UPDATE price = new.price;
SELECT * FROM products ORDER BY id;

DuckDB組み込み型の分析用

INSERT INTO products VALUES (2, 'みかん', '果物', 90), (6, 'バナナ', '果物', 100)
ON CONFLICT (id) DO UPDATE SET price = excluded.price;
SELECT * FROM products ORDER BY id;

MongoDBドキュメント指向データベース

db.products.updateOne({ _id: 2 }, { $set: { price: 90 } }, { upsert: true })
db.products.updateOne(
  { _id: 6 },
  { $set: { name: 'バナナ', category: '果物', price: 100 } },
  { upsert: true }
)
db.products.find({ _id: { $in: [2, 6] } })

Redisインメモリのキーバリューストア

HSET product:2 price 90
HSET product:6 name banana category fruit price 100
ZADD products:by_price 90 2 100 6
HGETALL product:2
HSETNX product:1 price 999
SET coupon:spring 10 NX
SET coupon:spring 20 NX
GET coupon:spring

グループごとに集計する

5つのページの同じお題のコードです。どれも、各ページの「準備」のデータを入れた後に流したものです。

PostgreSQLリレーショナルデータベース

SELECT category,
       COUNT(*) AS items,
       ROUND(AVG(price), 1) AS avg_price
FROM products
GROUP BY category
ORDER BY items DESC, category;

MySQLリレーショナルデータベース

SELECT category,
       COUNT(*) AS cnt,
       ROUND(AVG(price), 1) AS avg_price
FROM products
GROUP BY category
ORDER BY category;

DuckDB組み込み型の分析用

SELECT category, count(*) AS cnt, round(avg(price), 1) AS avg_price
FROM products
GROUP BY ALL
ORDER BY category;

MongoDBドキュメント指向データベース

db.products.aggregate([
  { $group: { _id: '$category', count: { $sum: 1 }, avg_price: { $avg: '$price' } } },
  { $sort: { _id: 1 } }
])

Redisインメモリのキーバリューストア

SCARD category:fruit
SCARD category:drink
SCARD category:bakery
HINCRBY qty_by_product 1 3
HINCRBY qty_by_product 1 2
HGET qty_by_product 1

関連する練習場

このページは静的な一覧で、入力欄はありません。各ページの練習場も、書いた SQL やコマンドをどこにも送りません。

このツールについて

よく使われる5つのデータベースの解説ページの入口です。同じ商品と注文のデータに同じお題を並べているので、SQL の方言の違いや、SQL を使わないデータベースでの考え方の違いを見比べられます。

PostgreSQL・MySQL・DuckDB・MongoDB・Redis を1表で比べ、同じお題の書き方を5つ並べて見比べられます。

主な機能

  • 5つのデータベースと SQLite の比較表(種類・誕生・ライセンス・練習場)
  • 同じお題(2ページ目を取る・あれば更新・集計)のコードを5つ並べて表示
  • 各解説ページの同じお題へ移れる
  • SQL の練習場・SQLAlchemy・SQL インジェクションのページへの案内
  • 静的ページ・送信ゼロ

よくある質問

Q. どのデータベースを選べばよいですか?

A. このページでは優劣を決めていません。多くの利用者が読み書きする Web サービスや業務システムには PostgreSQL や MySQL、手元のファイルの集計や分析には DuckDB、形が変わりやすいデータには MongoDB、キャッシュやランキングには Redis、といった得意な場面の違いを、各ページの概要とお題で比べられるようにしています。

Q. 練習場の「本物」と「再現」は何が違いますか?

A. 「本物」は PostgreSQL(PGlite)と DuckDB(DuckDB-WASM)で、ブラウザの中で本物の処理系が動きます。「再現」は MongoDB と Redis で、動きを JavaScript で再現したものです。MySQL はブラウザで動かせないため、練習場はありません。

Q. SQLite の解説ページはありますか?

A. 解説ページはありませんが、SQL を整える(/sql-playground/)で SQLite を実際に動かして、SELECT・INSERT・UPDATE・DELETE・JOIN を試せます。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

続けて整える

運営サイト

私たちが運営するサイト