目次


TL;DR

迷ったら選ぶもの
新規プロジェクトで特に制約がないPostgreSQL
既存資産・チームのノウハウが MySQL に寄っているMySQL
単純な CRUD 中心で、読み取りが多くレプリカで横に広げたいMySQL(どちらでも可)
複雑なクエリ・分析・JSON・地理空間・厳密な整合性が要るPostgreSQL
WordPress などの MySQL 前提の OSS を使うMySQL / MariaDB

最近は「特別な理由がなければ PostgreSQL」がデファクトになりつつあります。ただし MySQL が劣っているわけではなく、運用実績・チームの慣れ・エコシステムが選定理由として最も重いことが多いです。


1. 設計思想の違い

観点MySQL (InnoDB)PostgreSQL
思想シンプル・高速・運用しやすさ重視標準 SQL 準拠・拡張性・正確性重視
同時実行制御MVCC(undo ログ方式)MVCC(追記型。古い行は VACUUM で回収)
デフォルト分離レベルREPEATABLE READREAD COMMITTED
拡張性プラグインはあるが限定的Extension 文化が強い(PostGIS, pgvector, TimescaleDB など)
ライセンスGPL(Oracle 所有)/ 商用版ありPostgreSQL License(BSD 系、非常に緩い)

2. PostgreSQL が向いているケース

  • 複雑なクエリ・集計
    • CTE(再帰含む)、ウィンドウ関数、LATERAL、FILTER 句などが充実
    • オプティマイザがハッシュ結合・マージ結合などを柔軟に選び、複雑な JOIN に強い
  • JSON を本格的に扱う
    • jsonb + GIN インデックスで、JSON 内部を検索条件に使っても速い
  • データ型が豊富
    • 配列、範囲型(tstzrange など)、UUID、INET、列挙型、ドメイン型、複合型
    • 範囲型 + 排他制約(EXCLUDE)で「予約の重複禁止」を DB レベルで保証できる
  • 地理空間データ → PostGIS は事実上の業界標準
  • ベクトル検索(RAG など) → pgvector で既存 DB にそのまま追加できる
  • 厳密な整合性
    • DDL もトランザクション内で実行・ロールバック可能(マイグレーション失敗時に安全)
    • CHECK 制約、部分インデックス、式インデックス、遅延制約などが充実
  • 分析系ワークロードとの兼用
    • パラレルクエリ、マテリアライズドビュー、パーティショニング

3. MySQL が向いているケース

  • シンプルな OLTP(主キー検索・単純な CRUD)が大半
    • クラスタ化インデックス(主キー順に行を格納)により、主キー検索・範囲スキャンが速い
  • 読み取り中心で、レプリカで水平に広げたい
    • レプリケーションの運用実績・ツール(Orchestrator, ProxySQL, Vitess など)が豊富
  • 大規模シャーディング
    • Vitess(YouTube 発)や PlanetScale など、MySQL 互換で大規模に水平分割する選択肢が成熟
  • 既存資産・人材
    • WordPress、Magento などの OSS は MySQL 前提
    • 日本では特に Web 系で MySQL の運用ノウハウを持つエンジニアが多い
  • 運用の手軽さ
    • VACUUM のようなメンテナンスを意識する必要が少ない
    • 更新が非常に多いテーブルでも、PostgreSQL のような肥大化(bloat)が起きにくい

4. よくある落とし穴

MySQL

  • 文字コード:utf8 は 3 バイトで絵文字が入らない。必ず utf8mb4 を使う
  • sql_mode:緩い設定だと不正値が黙って切り詰め・変換される。STRICT_TRANS_TABLES を含む厳格モードを維持する
  • 照合順序(collation):大文字小文字・全角半角・濁点の区別がデフォルトでは期待と違うことがある(例:ハ と パ が同一視される照合順序がある)。要件に合わせて明示する
  • DDL はトランザクション外:マイグレーションが途中で失敗すると中途半端な状態が残る
  • 大きなテーブルの ALTER:Online DDL の対応範囲を確認するか、gh-ost / pt-online-schema-change を使う

PostgreSQL

  • VACUUM / autovacuum:更新・削除が多いテーブルは bloat しやすい。autovacuum の設定を監視・調整する
  • トランザクション ID 周回(wraparound):VACUUM が長期間回らないと深刻な障害になる。監視必須
  • コネクションが重い:1 接続 = 1 プロセス。PgBouncer などのコネクションプーラーはほぼ必須
  • 長時間トランザクション:古い行が回収できなくなり bloat の原因に。idle_in_transaction_session_timeout を設定する
  • 大文字の識別子:ダブルクォートで囲まないと小文字に変換される。テーブル名・カラム名は snake_case の小文字に統一する

5. マネージドサービスの選択肢

どちらも主要クラウドで提供されているため、クラウド選定が DB 選定の制約になることはほぼありません。

MySQLPostgreSQL
AWSRDS for MySQL, Aurora MySQLRDS for PostgreSQL, Aurora PostgreSQL
Google CloudCloud SQL for MySQLCloud SQL for PostgreSQL, AlloyDB
AzureAzure Database for MySQLAzure Database for PostgreSQL
その他PlanetScale, TiDB(MySQL 互換)Supabase, Neon, CockroachDB / YugabyteDB(PostgreSQL 互換)

各サービスの対応バージョンや料金は変わるため、採用時に公式ドキュメントで確認してください。


6. 判断フローチャート

既存システム・OSS が MySQL 前提?
 ├─ Yes → MySQL
 └─ No
     │
     チームの運用経験が片方に大きく偏っている?
      ├─ Yes → 慣れている方(運用できることが最優先)
      └─ No
          │
          JSON検索 / 地理空間 / ベクトル検索 / 複雑な分析クエリ が必要?
           ├─ Yes → PostgreSQL
           └─ No
               │
               超大規模な水平シャーディングが前提(Vitess 等を使いたい)?
                ├─ Yes → MySQL
                └─ No  → PostgreSQL(汎用性・拡張性で有利)

7. どちらを選んでも共通のベストプラクティス

  1. 主キーは必ず定義する(MySQL は特に、主キーがないと性能・レプリケーションに悪影響)
  2. ORM 任せにせず、実行計画(EXPLAIN)を確認する習慣をつける
  3. スロークエリログを有効にして定期的に見る
  4. マイグレーションはツールで管理(Flyway, Liquibase, Rails/Django/Prisma のマイグレーションなど)
  5. バックアップは「リストアできること」まで定期的に検証する
  6. DB 固有機能への依存は意識的に:便利な固有機能は積極的に使ってよいが、使った箇所を把握しておく
  7. タイムゾーンは UTC で保存(PostgreSQL は timestamptz、MySQL は接続のタイムゾーン設定に注意)

まとめ

  • 技術的な表現力・拡張性 → PostgreSQL が有利
  • シンプルさ・大規模水平分割の実績・既存エコシステム → MySQL が有利
  • 実務では 「チームが運用できるか」 が最も重要な選定基準
  • 白紙から選ぶなら PostgreSQL が無難なデフォルト

0件のページ