0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RedisとPostgreSQLを徹底比較!設計思想から処理速度まで検証してみた

Posted at

目次

1. はじめに

🔹 NoSQLとは?

スキーマレスで柔軟なデータ管理ができるデータベースの総称です。
高速処理やスケーラビリティに優れ、キャッシュやリアルタイム処理に適しています。

🔹 Redisとは?

インメモリ型のKey-Valueストアで、データを高速に扱えるNoSQLデータベースです。

🔹 なぜRedisを学ぶのか?

  • ゲームで使用されるキャッシュ・ランキング・リアルタイム処理に強い
  • RDB(特にPostgreSQL)との違いを理解することで、適材適所の選択ができる

🔹 本記事の目的

  • Redisの特徴を整理する
  • PostgreSQLとの違いを比較する
  • 実際に速度検証を行い、Redisの使いどころを見極める

2. Redisの基本的な特徴

2-1 高速なkey-valueストア

📌 メモリ上でのデータ管理により、高速アクセス(O(1))

  • Redis はすべてのデータを RAM上に保存しており、ディスクアクセスが発生しません
  • データ構造に ハッシュテーブル を採用しているため、キーによる検索は O(1) の高速処理
  • 数百万件規模のデータでも、ほぼ即時でアクセス可能です

📌 ディスクI/Oがないため、RDBより圧倒的に速い

  • 一般的な RDB(リレーショナルデータベース)は、ディスクI/Oを伴うため読み書きに時間がかかります
  • 一方 Redis は、メモリ上で全処理を完結させるため非常に高速です
  • 特に、キャッシュやランキング情報のように頻繁に読み書きされるデータでは、その高速性が大きなメリットになります

2-2 Redisのデータ構造

Redis には複数の基本データ型があり、それぞれ適した用途があります。
以下は代表的な5種類のデータ型とその使用例です。

データ型 主な用途
String "userId" → "Taro" シンプルな値の保存(キャッシュ、カウンター)
List ["A", "B", "C", "A"] 順序付きデータの管理(キュー、ログ)
Set {"A", "B", "C"} 重複なしデータの管理(ユーザIDリストなど)
Sorted Set (ZSET) {("A", 100), ("B", 200), ("C", 150)} スコア順で管理(ランキング機能など)
Hash(Keyとフィールドのペア) Key: "User123" / Fields: {"name": "Taro", "age": 30} オブジェクト形式の構造化データ(ユーザー情報など)

2-3 データ永続化のオプション

Redisはメモリ上にデータを保持する高速な仕組みですが、
永続化設定をしない場合、電源を落とすとデータは消えてしまいます。
このため、運用に応じた永続化の選択が重要になります。

🟢 RDB方式(スナップショット方式)

  • 一定間隔でメモリの状態をスナップショットとして保存し、ディスクへ書き込む
  • Redisのデフォルト設定
  • 書き込み頻度が少ないデータに向いている
    (例:構成情報、マスターデータなど)
  • 大量の書き込みがあると、保存タイミングによってはロスが出る可能性あり

🟠 AOF方式(ログ方式)

  • すべての書き込み操作をログとして記録
  • 順次ディスクに書き込むため、障害時の復元精度が高い
  • 書き込みが多いと ディスクI/Oの負荷が高くなる点には注意

🔵 ハイブリッド方式(RDB + AOF)

  • RDBの高速性と AOFの完全性を両立した方式
  • Redis 4.0以降のデフォルト推奨方式
  • 信頼性の高いサービス(金融・ゲーム等)でよく採用される

🚨 補足:
Redisはメモリ上で動作するため、永続化設定を行わないと電源断で全データが消えます。
本番運用では必ず何らかの永続化を有効にしておきましょう。


2-4 スケーラブルな設計

Redisはシンプルな構成ながら、負荷が増えても柔軟にスケールアウトできるよう設計されています。

⚙️ シングルスレッドで動作(ロック不要)

  • Redisはシングルスレッドで順番にコマンドを処理する設計
  • これにより、複雑なロック処理(排他制御など)が不要
  • 並列処理によるデッドロックや競合が発生しないため、常に安定して高速に動作

📡 レプリケーションで高可用性を確保

  • Redisはマスタースレーブ構成をサポート
  • データはマスターから自動的にスレーブへリアルタイム同期
  • 万が一マスターが停止しても、スレーブが代替として動作可能(フェイルオーバー)

🧩 シャーディングによる負荷分散

  • データを複数のRedisインスタンス(ノード)に分散して保存
  • 1台あたりの負荷を分散し、スループットと可用性を向上
  • 大量データや高頻度アクセスのあるシステムでも、スムーズに処理可能

2-5 主なユースケース

🚀 Redisは「高速処理が求められる場面」で特に威力を発揮します。
以下は代表的なユースケースとその活用例です。


🧠 キャッシュ(頻繁にアクセスするデータの保存)

  • よく参照されるデータをメモリ上に保持し、読み取りを高速化
  • データベースや外部APIへのアクセスを減らし、システム全体の負荷軽減に貢献

使用例:

  • 検索結果のキャッシュ
  • APIレスポンスの一時保存
  • ユーザープロフィール情報の保持

🏆 ランキング機能(Sorted Set を活用)

  • スコア付きデータを自動で順位付けし、ランキング順に取得可能
  • データの追加・スコア更新も高速で、リアルタイム性を維持しやすい

使用例:

  • ゲームのスコアランキング
  • 人気記事や商品レビューの上位表示

⚡ リアルタイムデータ処理(Pub/Sub)

  • Publish/Subscribeモデル により、イベント発生時に即時通知
  • 処理の非同期化や分散処理にも適している

使用例:

  • チャットアプリでのリアルタイムメッセージ配信
  • 通知サービスやアラート通知の即時処理

🔐 セッション管理(ログイン情報の一時保存)

  • ユーザーのログイン状態を保持し、毎回の認証コストを削減
  • セッション情報の保持にも軽量かつ高速で対応できる

使用例:

  • Webアプリのログインセッション管理
  • ショッピングカートの一時データ保存

3. RedisとPostgreSQLの違い

Redis(NoSQL)とPostgreSQL(RDB)は、そもそも設計思想が大きく異なります

  • Redisは「リアルタイム性」「軽量な高速処理」を重視
  • PostgreSQLは「整合性」「信頼性」「トランザクション管理」を重視

それぞれの違いを以下の観点で比較してみます。

🔄 Redis vs PostgreSQL 比較表

観点 Redis(NoSQL) PostgreSQL(RDB)
トランザクション整合性 基本なし(簡易的な MULTI/EXEC はあり) ACID準拠(順番に処理し、確実に記録)
応答の扱い 応答を待たずに複数コマンドを一括送信可能 1クエリずつ応答を受け取りながら処理
クライアント通信 redis-cli --pipe などによる一括送信+一括応答 JDBC / psql などで順番に送信・応答
エラー時の対応 エラーが混在しても動作継続(運用判断で対応) 失敗時は基本的にロールバックで巻き戻す
データ保存 メモリ保存(高速だが揮発性あり) ディスク保存(永続的で信頼性あり)
  • Redis:大量のコマンドを高速に流すことを重視(リアルタイム性重視)
  • PostgreSQL:整合性・堅牢性を重視(処理順と確実性が最優先)

だからこそ、データベース選定はユースケースに応じた「適材適所」が重要。


✅大量データを処理するには?

大量データを扱う際、RedisとPostgreSQLではアプローチが大きく異なります。
それぞれの特徴を以下に整理します。

🔴 Redis(NoSQL)の場合

  • ACID(整合性や永続性)を厳密には保証しない

  • 各コマンドの成功/失敗を逐次確認する必要がない

  • そのため、一括でコマンドを送信し、応答はまとめて受け取る方式が可能

    パイプライン方式(pipeline)

  • 複数のコマンドを一度に送信し、まとめて処理・応答を受け取る

  • 逐次応答を待たないため、大量データ処理でも非常に高速

🔵 PostgreSQL(RDB)の場合

  • ACID(原子性・整合性・一貫性・耐久性)を厳格に保証

  • 特にトランザクション整合性を重視し、1クエリずつ順番に処理・応答する設計

  • パイプラインのような一括通信には不向き

    バルク処理(Bulk Insert/Update)

  • 複数レコードを1つのSQL文にまとめて送信

  • トランザクション内で処理することで、整合性を保ちながらパフォーマンスを確保

🔍 まとめ

  • Redis:整合性よりもスピード重視 → パイプラインで超高速処理が可能
  • PostgreSQL:整合性重視 → 一括処理にはバルクSQLで対応

「何を重視するか(速度 or 安全性)」で、選ぶべき処理方式が変わってきます。


✅ RedisとPostgreSQLのその他の違い

RedisとPostgreSQLは、構造・設計・使いどころにおいて根本的な違いがあります。
以下に代表的な違いを表形式でまとめます。

項目 Redis(NoSQL) PostgreSQL(RDB)
データ保存 メモリ上(RAM)に保持 → 超高速アクセス ディスク(HDD/SSD)に保存 → 永続的で信頼性が高い
データ構造 Key-Value型(String, List, Hash など) リレーショナル型(テーブル・行・列)
スキーマ 不要(スキーマレス) → 柔軟にデータ管理可能 必要(スキーマあり) → 厳密な構造管理が可能
検索方法 キーによる高速検索(O(1)) SQLによる複雑な検索(JOINWHERE など)
トランザクション シンプル(MULTI / EXEC ACID完全対応(整合性・信頼性が求められる処理に最適)
用途 ランキング、リアルタイム処理、キャッシュ データの一貫性が重要な業務システム(会計、販売管理など)

🚀 ポイント:

  • Redis は「とにかく速く!」を重視した設計 → 高速処理が求められる用途に最適
  • PostgreSQL は「正確で安全に!」を重視した設計 → データ整合性が命の業務システム向け

両者は用途に応じて使い分けるのがベスト!

4. RedisとPostgreSQLの速度検証

📌 検証の目的

RedisとPostgreSQLで、追加・更新・削除処理の速度差を比較することで、
それぞれの特性に合った使い分けのヒントを得ることを目的としました。


📋 検証環境(Redis & PostgreSQL 共通)

項目 内容
OS macOS
実行環境 Docker
計測対象 Redis(version: 7.4.2) / PostgreSQL(version: 17.4)
計測回数 2回目〜4回目(計3回)を平均化( 1回目はキャッシュが無いため除外 )
測定方法 Docker CLI からコマンド実行+time計測
コマンド生成 事前に作成したコマンド・クエリを一括送信

🟥 Redis 側の検証条件

  • データ件数:100万件
  • 操作:検索・追加・更新・削除
  • 処理方式:パイプライン処理を使用
    ↳ 複数コマンドを一括で送信し、まとめて応答を受け取る

Redis:検証用コマンド一覧

クリックして展開(Redis コマンド一覧)

# 一件追加(HSET)
time docker exec -i <your_redis_container_name> redis-cli HSET user:1000001 name "User1000001" age 30 city "City1"

# 一件更新(HSETは上書き)
time docker exec -i <your_redis_container_name> redis-cli HSET user:1000001 name "UpdatedUser1000001" age 35 city "City2"

# 一件削除(DEL)
time docker exec -i <your_redis_container_name> redis-cli DEL user:1000001

# データ全削除(FLUSHALL)
docker exec -it <your_redis_container_name> redis-cli FLUSHALL

# 100万件追加(HSET + pipeline)
time (seq 1 1000000 | awk '{print "HSET user:"$1" name User"$1" age "20 + ($1 % 50)" city City"($1 % 10)}' \
| docker exec -i <your_redis_container_name> redis-cli --pipe)

# 100万件更新(HSET + pipeline)
time (seq 1 1000000 | awk '{print "HSET user:"$1" name UpdatedUser"$1" age "30 + ($1 % 50)" city UpdatedCity"($1 % 10)}' \
| docker exec -i <your_redis_container_name> redis-cli --pipe)

# 100万件削除(DEL + pipeline)
time (seq 1 1000000 | awk '{print "DEL user:"$1}' \
| docker exec -i <your_redis_container_name> redis-cli --pipe)

# 単純キー検索(HGET)
time docker exec -i <your_redis_container_name> redis-cli HGET user:12345 name

# 範囲検索(ZSET + ZRANGEBYSCORE)
# ① スコア付きでZSETに登録
time (seq 1 1000000 | awk '{print "ZADD users:score " $1 " user:"$1}' \
| docker exec -i <your_redis_container_name> redis-cli --pipe)

# ② スコア30以上のデータを抽出
time docker exec -i <your_redis_container_name> redis-cli ZRANGEBYSCORE users:score 30 +inf

# ランキング(ZREVRANGEでスコア上位100件を取得)
# ① ランダムスコアでZSETに登録
time (seq 1 1000000 | awk '{print "ZADD leaderboard " $1 " user:"$1}' | docker exec -i <your_redis_container_name> redis-cli --pipe)

# ② 上位100件取得(WITHSCORESでスコアも表示)
time docker exec -i <your_redis_container_name> redis-cli ZREVRANGE leaderboard 0 99 WITHSCORES


🟦 PostgreSQL 側の検証条件

  • 検証テーブル:3列(うち1列が主キー)
  • データ件数:100万件
  • 操作:検索・追加・更新・削除
  • 処理方式:プロシージャによるバルク処理を使用
    ↳ 1回のトランザクションで複数レコードをまとめて処理

PostgreSQL:検証用クエリ一覧

クリックして展開(PostgreSQL クエリ一覧)

# PostgreSQL テーブル作成
docker exec -i postgres-container psql -U your_user -d your_database -c "
CREATE TABLE leaderboard (
    id SERIAL PRIMARY KEY,
    username TEXT NOT NULL,
    score INT NOT NULL
);"

# PostgreSQL テーブル初期化
time docker exec -i postgres-container psql -U your_user -d your_database -c "TRUNCATE TABLE leaderboard RESTART IDENTITY;"

# PostgreSQL 一件追加
time docker exec -i postgres-container psql -U your_user -d your_database -c "
INSERT INTO leaderboard (username, score) VALUES ('user_1000001', 1000001);"

# PostgreSQL 100万件追加(バルク + トランザクション)
time (
  echo "BEGIN;"
  echo "INSERT INTO leaderboard (username, score) VALUES"
  seq 1 1000000 | awk '{print "( '\''user_"$1"'\'', " $1 ")"}' | paste -sd, -
  echo ";"
  echo "COMMIT;"
) | docker exec -i postgres-container psql -q -U your_user -d your_database

# PostgreSQL 一件更新
time docker exec -i postgres-container psql -U your_user -d your_database -c "
UPDATE leaderboard SET score = 999999 WHERE id = 500000;"

# PostgreSQL 100万件更新
time (
  echo "BEGIN;"
  seq 1 1000000 | awk '{print "UPDATE leaderboard SET score = " $1 " WHERE id = " $1 ";"}'
  echo "COMMIT;"
) | docker exec -i postgres-container psql -q -U your_user -d your_database

# PostgreSQL 一件削除
time docker exec -i postgres-container psql -U your_user -d your_database -c "
DELETE FROM leaderboard WHERE id = 500000;"

# PostgreSQL 100万件削除(バルク + トランザクション)
time (
  echo "BEGIN;"
  seq 1 1000000 | awk '{print "DELETE FROM leaderboard WHERE id = " $1 ";"}'
  echo "COMMIT;"
) | docker exec -i postgres-container psql -q -U your_user -d your_database

# PostgreSQL 単純キー検索
time docker exec -i postgres-container psql -U your_user -d your_database -c \
"SELECT * FROM leaderboard WHERE id = 12345;"

# PostgreSQL 範囲検索(score 30以上)
time docker exec -i postgres-container psql -U your_user -d your_database -c \
"SELECT * FROM leaderboard WHERE score >= 30;"

# PostgreSQL ランキング(上位100件)
time docker exec -i postgres-container psql -U your_user -d your_database -c \
"SELECT * FROM leaderboard ORDER BY score DESC LIMIT 100;"


✅ 補足:パイプライン処理とバルク処理の違い

RedisとPostgreSQLは、大量データを高速に処理するための方法として
それぞれ異なるアプローチ(パイプライン処理/バルク処理)を持っています。

以下は両者の比較表です。

比較項目 Redis のパイプライン処理 PostgreSQL のバルク処理
処理方式 複数のコマンドを一括で送信・まとめて応答を受信 複数レコードを 1つのSQL文にまとめて処理
目的 通信の往復回数を減らして高速化 SQLのパース回数・トランザクション回数を削減し高速化
対象 Redisコマンド(SET, HSET, ZADD など) SQLクエリ(INSERT, UPDATE, DELETE など)
クライアントの役割 コマンドを事前に組み立てて --pipe などで送信 SQL文を生成して 1つのクエリにまとめる
サーバの動作 受け取ったコマンドを順に実行 1回でSQLをパース・最適化して一括処理
効果が出やすい条件 ネットワークのレイテンシが高く、応答に時間がかかる環境 レコード数が多く、1件ずつSQLを発行するのが非効率な場合
主なユースケース 大量データの一括登録、更新、削除 INSERTUPDATE の一括実行、COPY 処理など

🔸 データ追加・更新・削除の比較

カテゴリ Redisの処理内容 結果 (秒) PostgreSQLの処理内容 結果 (秒)
追加(1件) HSET で1件のユーザーデータを追加 0.209 INSERT文を1件生成し、BEGINCOMMITで実行 0.243
追加(100万件) HSETコマンドを100万件分生成し、--pipeでパイプライン一括送信 4.283 INSERT文を100万件生成し、BEGINCOMMITで一括実行 6.230
更新(1件) 同じキーに HSET で再設定(上書き) 0.201 UPDATE文を1件(WHERE id=◯◯◯)実行、BEGINCOMMIT 0.274
更新(100万件) 既存100万キーに HSET で再設定、--pipe 使用 3.838 UPDATE文を100万件生成(WHERE id=◯◯◯)、BEGINCOMMIT 147.610
削除(1件) DEL で1キー削除 0.224 DELETE文を1件(WHERE id=◯◯◯)、BEGINCOMMIT 0.246
削除(100万件) DELコマンドを100万件分生成し、--pipeで一括削除 1.535 DELETE文を100万件(WHERE id=◯◯◯)、BEGINCOMMIT 151.800

🔸 検索・ランキングの比較

カテゴリ Redisの処理内容 結果 (秒) PostgreSQLの処理内容 結果 (秒)
単純キー検索 HGET で特定フィールドを検索(1件想定、O(1)) 0.217 SELECT * FROM ~ WHERE id=◯◯◯ で1件取得 0.257
範囲検索 ZADD でスコア付き登録 → ZRANGEBYSCORE で30以上を抽出 1.338 WHERE score >= 30 で範囲検索 3.994
ランキング取得 ZREVRANGE でスコア上位100件を取得 0.212 ORDER BY score DESC LIMIT 100 で上位100件を取得 0.289

5. RedisとPostgreSQLの組み合わせ

🔄 Redis × PostgreSQL の役割分担

  • Redis:リアルタイム処理や一時的なキャッシュ処理に強み
  • PostgreSQL:永続的なデータ保存や複雑な集計、整合性の管理に優れる

💡 組み合わせるメリット

  • 頻繁にアクセスするデータを Redis にキャッシュ
    → アプリケーションの応答速度を大幅に改善できる
  • 更新・保存が必要なデータは PostgreSQL に記録
    → データの信頼性やトランザクション管理が担保される

✅ それぞれの強みを活かしたベストミックスな構成が可能!


🎮 活用例(ゲーム開発の場合)

処理内容 使用データベース 理由
ランキング、セッション管理 Redis 高速アクセスが求められるため
プレイヤープロフィール、課金履歴 PostgreSQL データの整合性・履歴保持が必要なため

✅ 一言で言うなら・・・

💡 リアルタイム性と整合性の両立が求められるアプリケーションでは、RedisとPostgreSQLは“相互補完”の関係になれる!

6. まとめ

📌 RedisとPostgreSQLの比較からわかったこと

  • Redis:リアルタイム性・高速性に優れ、一時的なデータ管理やランキング処理に最適
  • PostgreSQL:整合性・複雑な検索・集計処理に強く、永続的なデータ管理に最適

🚀 速度検証の結果から見えたこと

  • 1件ごとの処理速度は両者とも非常に高速
  • 大量データの処理では Redis(パイプライン処理)の方が圧倒的に高速
  • 一方、PostgreSQLは ACID準拠による処理の信頼性確保のため、どうしても処理に時間がかかる

🔎 処理速度だけでなく、「どのような目的のシステムか」によって選択肢を変える必要がある

✅ RedisとPostgreSQLは“目的”が違う

💡 RedisとPostgreSQLはそもそも設計思想が異なるため、単純な速度比較だけでは本質を見誤る可能性がある。

  • Redis:速度重視・柔軟性
  • PostgreSQL:整合性・堅牢性

🎯 重要なのは「適材適所」で活用すること!


🔚 最後に

  • それぞれの強みを理解して、役割を分担するような設計が最も効果的
  • リアルタイム性と整合性の“いいとこ取り”を意識した設計を目指していこう!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?