PostgreSQL と MySQL の概要

リレーショナルデータベースの二大巨頭、PostgreSQLMySQLを比較します。どちらもオープンソースで無料、長い歴史と大規模な導入実績を持ちます。

基本情報

項目PostgreSQLMySQL
開発元PostgreSQL Global Development GroupOracle Corporation
初回リリース1996年1995年
ライセンスPostgreSQL License(BSD系)GPL v2(商用はOracle)
哲学機能の豊富さ・標準準拠シンプルさ・速度
代表的な利用者Apple, Instagram, SpotifyFacebook, Twitter, Uber

機能比較

機能PostgreSQLMySQL
JSON/JSONB◎ ネイティブ対応○ JSON型あり
全文検索◎ 内蔵(日本語対応)○ InnoDB全文検索
GIS/地理空間◎ PostGIS○ Spatial拡張
マテリアライズドビュー○ 対応× 非対応
CTE (WITH句)◎ 再帰CTE対応○ 対応
Window関数◎ 豊富○ 対応
配列型○ 対応× 非対応
Enum型○ 対応○ 対応
ストアドプロシージャ○ PL/pgSQL等○ 対応
パーティショニング○ 宣言的○ 対応
レプリケーション○ 論理/物理◎ 成熟

SQL の違い

文字列の扱い

-- PostgreSQL: シングルクォートのみ
SELECT 'Hello World';
SELECT "column_name" FROM users;  -- ダブルクォートは識別子

-- MySQL: シングル/ダブルどちらもOK(デフォルト)
SELECT 'Hello World';
SELECT "Hello World";  -- これも文字列
SELECT `column_name` FROM users;  -- バッククォートが識別子

UPSERT(INSERT or UPDATE)

-- PostgreSQL: ON CONFLICT
INSERT INTO users (email, name)
VALUES ('[email protected]', '田中')
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name;

-- MySQL: ON DUPLICATE KEY UPDATE
INSERT INTO users (email, name)
VALUES ('[email protected]', '田中')
ON DUPLICATE KEY UPDATE name = VALUES(name);

LIMIT + OFFSET

-- PostgreSQL
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;

-- MySQL(同じ構文が使える)
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;
-- MySQL独自構文
SELECT * FROM users ORDER BY id LIMIT 20, 10;

AUTO INCREMENT

-- PostgreSQL: SERIAL or GENERATED
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  -- or
  id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY
);

-- MySQL: AUTO_INCREMENT
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY
);

日付・時刻

-- PostgreSQL
SELECT NOW();                          -- タイムスタンプ
SELECT CURRENT_DATE;                   -- 日付
SELECT EXTRACT(YEAR FROM NOW());       -- 年を抽出
SELECT '2026-03-31'::DATE;             -- キャスト

-- MySQL
SELECT NOW();                          -- 日時
SELECT CURDATE();                      -- 日付
SELECT YEAR(NOW());                    -- 年を抽出
SELECT CAST('2026-03-31' AS DATE);     -- キャスト

JSON の扱い

PostgreSQL の JSONB

PostgreSQLの JSONB は非常に強力です:

-- JSONB カラムを持つテーブル
CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  attributes JSONB DEFAULT '{}'
);

-- データ挿入
INSERT INTO products (name, attributes) VALUES
  ('ノートPC', '{"brand": "Apple", "ram": 16, "tags": ["laptop", "mac"]}');

-- JSON内のフィールドで検索
SELECT * FROM products
WHERE attributes->>'brand' = 'Apple';

-- JSON内のフィールドでフィルタ(数値比較)
SELECT * FROM products
WHERE (attributes->>'ram')::int >= 16;

-- 配列の中を検索
SELECT * FROM products
WHERE attributes->'tags' ? 'laptop';

-- GIN インデックスで高速化
CREATE INDEX idx_products_attrs ON products USING GIN (attributes);

-- JSON パスクエリ(PostgreSQL 12+)
SELECT * FROM products
WHERE attributes @? '$.tags[*] ? (@ == "laptop")';

MySQL の JSON

-- JSON カラム
CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  attributes JSON
);

-- JSON内のフィールドで検索
SELECT * FROM products
WHERE JSON_EXTRACT(attributes, '$.brand') = 'Apple';

-- ショートハンド
SELECT * FROM products
WHERE attributes->>'$.brand' = 'Apple';

-- JSON検索はインデックスが効きにくい(仮想カラムで対応)
ALTER TABLE products
ADD COLUMN brand VARCHAR(50)
GENERATED ALWAYS AS (attributes->>'$.brand') STORED;

CREATE INDEX idx_brand ON products (brand);

PostgreSQLの方がJSONの扱いが強力です。

パフォーマンス特性

読み取り性能

単純なSELECTクエリでは大きな差はありませんが、特性が異なります:

シナリオPostgreSQLMySQL
単純なSELECT
複雑なJOIN
サブクエリ
集計(GROUP BY)

書き込み性能

シナリオPostgreSQLMySQL
単純なINSERT
バルクINSERT
UPDATE(大量)
MVCC効率

接続管理

PostgreSQL: プロセスベース(1接続=1プロセス)
  → PgBouncer等の接続プーラーが推奨

MySQL: スレッドベース(1接続=1スレッド)
  → 軽量で多数の接続を処理しやすい

拡張性

PostgreSQL の拡張機能

-- 拡張機能のインストール
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";  -- UUID生成
CREATE EXTENSION IF NOT EXISTS "pg_trgm";     -- トライグラム全文検索
CREATE EXTENSION IF NOT EXISTS "postgis";     -- 地理空間データ

-- UUID生成
SELECT uuid_generate_v4();

-- あいまい検索
SELECT * FROM products
WHERE name % 'ノートパソコン'  -- トライグラム類似検索
ORDER BY similarity(name, 'ノートパソコン') DESC;

主要な拡張機能:

拡張機能
PostGIS地理空間データ処理
pg_trgmトライグラム全文検索
uuid-osspUUID生成
pgcrypto暗号化関数
pg_stat_statementsクエリ統計
timescaledb時系列データ
pgvectorベクトル検索(AI/ML)

MySQL のプラグイン

MySQLもプラグインで拡張できますが、PostgreSQLほどの柔軟性はありません。

クラウドサービス

サービスPostgreSQLMySQL
AWSRDS, Aurora PostgreSQLRDS, Aurora MySQL
GCPCloud SQL, AlloyDBCloud SQL
AzureAzure Database for PostgreSQLAzure Database for MySQL
サーバーレスNeon, SupabasePlanetScale

ORM との相性

Prisma

// どちらもPrismaで使える
datasource db {
  provider = "postgresql"  // or "mysql"
  url      = env("DATABASE_URL")
}

Drizzle ORM

// PostgreSQL
import { pgTable, serial, text } from 'drizzle-orm/pg-core';

const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
});

// MySQL
import { mysqlTable, int, varchar } from 'drizzle-orm/mysql-core';

const users = mysqlTable('users', {
  id: int('id').primaryKey().autoincrement(),
  name: varchar('name', { length: 255 }).notNull(),
});

選定ガイド

PostgreSQL を選ぶべきケース

  • 複雑なクエリ: JOIN、サブクエリ、CTEが多い
  • JSON データ: JSONBの強力な機能が必要
  • 地理空間データ: PostGISが必要
  • 拡張性: カスタム型、関数、拡張機能が必要
  • SQL標準準拠: 標準SQLに忠実なコードを書きたい
  • ベクトル検索: pgvectorでAI/ML機能を統合

MySQL を選ぶべきケース

  • シンプルなCRUD: 単純な読み書きが中心
  • 高い同時接続数: 軽量な接続管理
  • 既存の知見: チームがMySQLに精通している
  • レプリケーション: 成熟したレプリケーション機能
  • WordPress/PHP: PHPエコシステムとの親和性

まとめ

判断軸PostgreSQLMySQL
機能の豊富さ
JSON対応
学習コスト
単純な読み書き
拡張性
クラウド対応

2026年のWebアプリケーション開発では、PostgreSQLが第一選択になるケースが増えています。特にJSON対応、拡張機能、SQL標準準拠の面で優れています。一方、MySQLもシンプルなアプリケーションでは十分な選択肢です。


SQLクエリの結果をJSON形式で確認する際は、AssistyのJSONフォーマッターで見やすく整形できます。